diff --git a/packages/contracts-bedrock/interfaces/L2/IFeeVault.sol b/packages/contracts-bedrock/interfaces/L2/IFeeVault.sol index 2afe02f90d6..4514225beb4 100644 --- a/packages/contracts-bedrock/interfaces/L2/IFeeVault.sol +++ b/packages/contracts-bedrock/interfaces/L2/IFeeVault.sol @@ -4,19 +4,27 @@ pragma solidity ^0.8.0; import { Types } from "src/libraries/Types.sol"; interface IFeeVault { + error FeeSplitter_OnlyProxyAdminOwner(); + event Withdrawal(uint256 value, address to, address from); event Withdrawal(uint256 value, address to, address from, Types.WithdrawalNetwork withdrawalNetwork); + event MinWithdrawalAmountUpdated(uint256 oldWithdrawalAmount, uint256 newWithdrawalAmount); + event RecipientUpdated(address oldRecipient, address newRecipient); + event WithdrawalNetworkUpdated(Types.WithdrawalNetwork oldWithdrawalNetwork, Types.WithdrawalNetwork newWithdrawalNetwork); receive() external payable; function MIN_WITHDRAWAL_AMOUNT() external view returns (uint256); function RECIPIENT() external view returns (address); function WITHDRAWAL_NETWORK() external view returns (Types.WithdrawalNetwork); - function minWithdrawalAmount() external view returns (uint256 amount_); - function recipient() external view returns (address recipient_); + function minWithdrawalAmount() external view returns (uint256); + function recipient() external view returns (address); function totalProcessed() external view returns (uint256); function withdraw() external; - function withdrawalNetwork() external view returns (Types.WithdrawalNetwork network_); + function withdrawalNetwork() external view returns (Types.WithdrawalNetwork); + function setMinWithdrawalAmount(uint256 _newMinWithdrawalAmount) external; + function setRecipient(address _newRecipient) external; + function setWithdrawalNetwork(Types.WithdrawalNetwork _newWithdrawalNetwork) external; function __constructor__() external; } diff --git a/packages/contracts-bedrock/interfaces/L2/IFeeVaultInitializer.sol b/packages/contracts-bedrock/interfaces/L2/IFeeVaultInitializer.sol new file mode 100644 index 00000000000..da5d6debe84 --- /dev/null +++ b/packages/contracts-bedrock/interfaces/L2/IFeeVaultInitializer.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Types } from "src/libraries/Types.sol"; + +interface IFeeVaultInitializer { + /// @notice Emitted when a fee vault implementation is deployed. + /// @param vaultType The type of fee vault being deployed. + /// @param newImplementation The deployed implementation address. + /// @param recipient The recipient address for the implementation. + /// @param network The withdrawal network for the implementation. + /// @param minWithdrawalAmount The minimum withdrawal amount for the implementation. + event FeeVaultDeployed( + string indexed vaultType, + address indexed newImplementation, + address recipient, + Types.WithdrawalNetwork network, + uint256 minWithdrawalAmount + ); + + function version() external view returns (string memory); +} \ No newline at end of file diff --git a/packages/contracts-bedrock/scripts/L2Genesis.s.sol b/packages/contracts-bedrock/scripts/L2Genesis.s.sol index 40aae9e1b2a..ef9c5eb2ebd 100644 --- a/packages/contracts-bedrock/scripts/L2Genesis.s.sol +++ b/packages/contracts-bedrock/scripts/L2Genesis.s.sol @@ -587,8 +587,7 @@ contract L2Genesis is Script { // Initialize the proxy with the actual values IFeeSplitter(payable(Predeploys.FEE_SPLITTER)).initialize( - ISharesCalculator(_input.feeSplitterSharesCalculator), - uint128(_input.feeSplitterFeeDisbursementInterval) + ISharesCalculator(_input.feeSplitterSharesCalculator), uint128(_input.feeSplitterFeeDisbursementInterval) ); } diff --git a/packages/contracts-bedrock/snapshots/abi/BaseFeeVault.json b/packages/contracts-bedrock/snapshots/abi/BaseFeeVault.json index b745bcb8184..2b4121958e1 100644 --- a/packages/contracts-bedrock/snapshots/abi/BaseFeeVault.json +++ b/packages/contracts-bedrock/snapshots/abi/BaseFeeVault.json @@ -69,7 +69,7 @@ "outputs": [ { "internalType": "uint256", - "name": "amount_", + "name": "", "type": "uint256" } ], @@ -82,13 +82,52 @@ "outputs": [ { "internalType": "address", - "name": "recipient_", + "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newMinWithdrawalAmount", + "type": "uint256" + } + ], + "name": "setMinWithdrawalAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newRecipient", + "type": "address" + } + ], + "name": "setRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum Types.WithdrawalNetwork", + "name": "_newWithdrawalNetwork", + "type": "uint8" + } + ], + "name": "setWithdrawalNetwork", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "totalProcessed", @@ -128,13 +167,51 @@ "outputs": [ { "internalType": "enum Types.WithdrawalNetwork", - "name": "network_", + "name": "", "type": "uint8" } ], "stateMutability": "view", "type": "function" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldWithdrawalAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newWithdrawalAmount", + "type": "uint256" + } + ], + "name": "MinWithdrawalAmountUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldRecipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newRecipient", + "type": "address" + } + ], + "name": "RecipientUpdated", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -190,5 +267,29 @@ ], "name": "Withdrawal", "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "enum Types.WithdrawalNetwork", + "name": "oldWithdrawalNetwork", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum Types.WithdrawalNetwork", + "name": "newWithdrawalNetwork", + "type": "uint8" + } + ], + "name": "WithdrawalNetworkUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "FeeSplitter_OnlyProxyAdminOwner", + "type": "error" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/FeeSplitter.json b/packages/contracts-bedrock/snapshots/abi/FeeSplitter.json index 5f5f234015f..565fb208fe4 100644 --- a/packages/contracts-bedrock/snapshots/abi/FeeSplitter.json +++ b/packages/contracts-bedrock/snapshots/abi/FeeSplitter.json @@ -8,58 +8,6 @@ "stateMutability": "payable", "type": "receive" }, - { - "inputs": [], - "name": "BASIS_POINT_SCALE", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MIN_FEE_DISBURSEMENT_INTERVAL", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "_PAYOUT_CLOSED", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "_PAYOUT_OPEN", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "disburseFees", @@ -72,22 +20,9 @@ "name": "feeDisbursementInterval", "outputs": [ { - "internalType": "uint40", + "internalType": "uint128", "name": "", - "type": "uint40" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "grossFeeShareBP", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" + "type": "uint128" } ], "stateMutability": "view", @@ -96,29 +31,14 @@ { "inputs": [ { - "internalType": "address payable", - "name": "_revenueShareRecipient", + "internalType": "contract ISharesCalculator", + "name": "_shareCalculator", "type": "address" }, { - "internalType": "address payable", - "name": "_revenueRemainderRecipient", - "type": "address" - }, - { - "internalType": "uint40", + "internalType": "uint128", "name": "_feeDisbursementInterval", - "type": "uint40" - }, - { - "internalType": "uint16", - "name": "_netFeeShareBP", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "_grossFeeShareBP", - "type": "uint16" + "type": "uint128" } ], "name": "initialize", @@ -131,74 +51,9 @@ "name": "lastDisbursementTime", "outputs": [ { - "internalType": "uint40", - "name": "", - "type": "uint40" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "netFeeRevenue", - "outputs": [ - { - "internalType": "uint144", - "name": "", - "type": "uint144" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "netFeeShareBP", - "outputs": [ - { - "internalType": "uint16", + "internalType": "uint128", "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "payoutGateState", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "revenueRemainderRecipient", - "outputs": [ - { - "internalType": "address payable", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "revenueShareRecipient", - "outputs": [ - { - "internalType": "address payable", - "name": "", - "type": "address" + "type": "uint128" } ], "stateMutability": "view", @@ -207,9 +62,9 @@ { "inputs": [ { - "internalType": "uint40", + "internalType": "uint128", "name": "_newFeeDisbursementInterval", - "type": "uint40" + "type": "uint128" } ], "name": "setFeeDisbursementInterval", @@ -220,53 +75,27 @@ { "inputs": [ { - "internalType": "uint16", - "name": "_newGrossFeeShareBP", - "type": "uint16" - } - ], - "name": "setGrossFeeShareBP", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "_newNetFeeShareBP", - "type": "uint16" - } - ], - "name": "setNetFeeShareBP", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_newRevenueRemainderRecipient", + "internalType": "contract ISharesCalculator", + "name": "_newShareCalculator", "type": "address" } ], - "name": "setRevenueRemainderRecipient", + "name": "setShareCalculator", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "shareCalculator", + "outputs": [ { - "internalType": "address", - "name": "_newRevenueShareRecipient", + "internalType": "contract ISharesCalculator", + "name": "", "type": "address" } ], - "name": "setRevenueShareRecipient", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -287,15 +116,15 @@ "inputs": [ { "indexed": false, - "internalType": "uint40", + "internalType": "uint128", "name": "oldFeeDisbursementInterval", - "type": "uint40" + "type": "uint128" }, { "indexed": false, - "internalType": "uint40", + "internalType": "uint128", "name": "newFeeDisbursementInterval", - "type": "uint40" + "type": "uint128" } ], "name": "FeeDisbursementIntervalUpdated", @@ -305,27 +134,27 @@ "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "uint256", - "name": "disbursementTime", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "revenueShareRecipientAmount", - "type": "uint256" - }, - { + "components": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], "indexed": false, - "internalType": "uint256", - "name": "revenueRemainderRecipientAmount", - "type": "uint256" + "internalType": "struct ShareInfo[]", + "name": "shareInfo", + "type": "tuple[]" }, { "indexed": false, "internalType": "uint256", - "name": "totalFeesDisbursed", + "name": "grossRevenue", "type": "uint256" } ], @@ -351,62 +180,6 @@ "name": "FeesReceived", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint16", - "name": "oldGrossFeeShareBP", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "newGrossFeeShareBP", - "type": "uint16" - } - ], - "name": "GrossFeeShareBPUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address payable", - "name": "revenueShareRecipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "address payable", - "name": "revenueRemainderRecipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint40", - "name": "feeDisbursementInterval", - "type": "uint40" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "netFeeShareBP", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "grossFeeShareBP", - "type": "uint16" - } - ], - "name": "Initialized", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -425,62 +198,37 @@ "inputs": [ { "indexed": false, - "internalType": "uint16", - "name": "oldNetFeeShareBP", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "newNetFeeShareBP", - "type": "uint16" - } - ], - "name": "NetFeeShareBPUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "NoFeesCollected", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "oldRevenueRemainderRecipient", + "internalType": "contract ISharesCalculator", + "name": "shareCalculator", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newRevenueRemainderRecipient", - "type": "address" + "indexed": false, + "internalType": "uint128", + "name": "feeDisbursementInterval", + "type": "uint128" } ], - "name": "RevenueRemainderRecipientUpdated", + "name": "Initialized", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "oldRevenueShareRecipient", + "name": "oldShareCalculator", "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "newRevenueShareRecipient", + "name": "newShareCalculator", "type": "address" } ], - "name": "RevenueShareRecipientUpdated", + "name": "ShareCalculatorUpdated", "type": "event" }, { @@ -488,11 +236,6 @@ "name": "FeeSplitter_DisbursementIntervalNotReached", "type": "error" }, - { - "inputs": [], - "name": "FeeSplitter_FailedToSendToRevenueRemainderRecipient", - "type": "error" - }, { "inputs": [], "name": "FeeSplitter_FailedToSendToRevenueShareRecipient", @@ -500,12 +243,7 @@ }, { "inputs": [], - "name": "FeeSplitter_FeeDisbursementIntervalTooShort", - "type": "error" - }, - { - "inputs": [], - "name": "FeeSplitter_FeeShareBPExceeds100Percent", + "name": "FeeSplitter_FeeShareInfoEmpty", "type": "error" }, { @@ -520,42 +258,32 @@ }, { "inputs": [], - "name": "FeeSplitter_GrossFeeShareBPExceeds100Percent", - "type": "error" - }, - { - "inputs": [], - "name": "FeeSplitter_NewFeeDisbursementIntervalTooShort", + "name": "FeeSplitter_NoFeesCollected", "type": "error" }, { "inputs": [], - "name": "FeeSplitter_NewRevenueRemainderRecipientCannotBeZero", - "type": "error" - }, - { - "inputs": [], - "name": "FeeSplitter_NewRevenueShareRecipientCannotBeZero", + "name": "FeeSplitter_OnlyProxyAdminOwner", "type": "error" }, { "inputs": [], - "name": "FeeSplitter_OnlyProxyAdminOwner", + "name": "FeeSplitter_ReceiveWindowClosed", "type": "error" }, { "inputs": [], - "name": "FeeSplitter_ReceiveDisabledDuringPayout", + "name": "FeeSplitter_SenderNotApprovedVault", "type": "error" }, { "inputs": [], - "name": "FeeSplitter_RevenueRemainderRecipientCannotBeZero", + "name": "FeeSplitter_ShareCalculatorCannotBeZero", "type": "error" }, { "inputs": [], - "name": "FeeSplitter_RevenueShareRecipientCannotBeZero", + "name": "FeeSplitter_ShareCalculatorMalformedOutput", "type": "error" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/FeeVaultInitializer.json b/packages/contracts-bedrock/snapshots/abi/FeeVaultInitializer.json new file mode 100644 index 00000000000..87b58357d78 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/abi/FeeVaultInitializer.json @@ -0,0 +1,57 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "string", + "name": "vaultType", + "type": "string" + }, + { + "indexed": true, + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum Types.WithdrawalNetwork", + "name": "network", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "minWithdrawalAmount", + "type": "uint256" + } + ], + "name": "FeeVaultDeployed", + "type": "event" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/L1FeeVault.json b/packages/contracts-bedrock/snapshots/abi/L1FeeVault.json index b745bcb8184..2b4121958e1 100644 --- a/packages/contracts-bedrock/snapshots/abi/L1FeeVault.json +++ b/packages/contracts-bedrock/snapshots/abi/L1FeeVault.json @@ -69,7 +69,7 @@ "outputs": [ { "internalType": "uint256", - "name": "amount_", + "name": "", "type": "uint256" } ], @@ -82,13 +82,52 @@ "outputs": [ { "internalType": "address", - "name": "recipient_", + "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newMinWithdrawalAmount", + "type": "uint256" + } + ], + "name": "setMinWithdrawalAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newRecipient", + "type": "address" + } + ], + "name": "setRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum Types.WithdrawalNetwork", + "name": "_newWithdrawalNetwork", + "type": "uint8" + } + ], + "name": "setWithdrawalNetwork", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "totalProcessed", @@ -128,13 +167,51 @@ "outputs": [ { "internalType": "enum Types.WithdrawalNetwork", - "name": "network_", + "name": "", "type": "uint8" } ], "stateMutability": "view", "type": "function" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldWithdrawalAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newWithdrawalAmount", + "type": "uint256" + } + ], + "name": "MinWithdrawalAmountUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldRecipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newRecipient", + "type": "address" + } + ], + "name": "RecipientUpdated", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -190,5 +267,29 @@ ], "name": "Withdrawal", "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "enum Types.WithdrawalNetwork", + "name": "oldWithdrawalNetwork", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum Types.WithdrawalNetwork", + "name": "newWithdrawalNetwork", + "type": "uint8" + } + ], + "name": "WithdrawalNetworkUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "FeeSplitter_OnlyProxyAdminOwner", + "type": "error" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/OperatorFeeVault.json b/packages/contracts-bedrock/snapshots/abi/OperatorFeeVault.json index 657c3d27808..2b4121958e1 100644 --- a/packages/contracts-bedrock/snapshots/abi/OperatorFeeVault.json +++ b/packages/contracts-bedrock/snapshots/abi/OperatorFeeVault.json @@ -1,6 +1,22 @@ [ { - "inputs": [], + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_minWithdrawalAmount", + "type": "uint256" + }, + { + "internalType": "enum Types.WithdrawalNetwork", + "name": "_withdrawalNetwork", + "type": "uint8" + } + ], "stateMutability": "nonpayable", "type": "constructor" }, @@ -53,7 +69,7 @@ "outputs": [ { "internalType": "uint256", - "name": "amount_", + "name": "", "type": "uint256" } ], @@ -66,13 +82,52 @@ "outputs": [ { "internalType": "address", - "name": "recipient_", + "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newMinWithdrawalAmount", + "type": "uint256" + } + ], + "name": "setMinWithdrawalAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newRecipient", + "type": "address" + } + ], + "name": "setRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum Types.WithdrawalNetwork", + "name": "_newWithdrawalNetwork", + "type": "uint8" + } + ], + "name": "setWithdrawalNetwork", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "totalProcessed", @@ -112,13 +167,51 @@ "outputs": [ { "internalType": "enum Types.WithdrawalNetwork", - "name": "network_", + "name": "", "type": "uint8" } ], "stateMutability": "view", "type": "function" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldWithdrawalAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newWithdrawalAmount", + "type": "uint256" + } + ], + "name": "MinWithdrawalAmountUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldRecipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newRecipient", + "type": "address" + } + ], + "name": "RecipientUpdated", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -174,5 +267,29 @@ ], "name": "Withdrawal", "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "enum Types.WithdrawalNetwork", + "name": "oldWithdrawalNetwork", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum Types.WithdrawalNetwork", + "name": "newWithdrawalNetwork", + "type": "uint8" + } + ], + "name": "WithdrawalNetworkUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "FeeSplitter_OnlyProxyAdminOwner", + "type": "error" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/SequencerFeeVault.json b/packages/contracts-bedrock/snapshots/abi/SequencerFeeVault.json index 700e7d7b981..fd70ca64640 100644 --- a/packages/contracts-bedrock/snapshots/abi/SequencerFeeVault.json +++ b/packages/contracts-bedrock/snapshots/abi/SequencerFeeVault.json @@ -82,7 +82,7 @@ "outputs": [ { "internalType": "uint256", - "name": "amount_", + "name": "", "type": "uint256" } ], @@ -95,13 +95,52 @@ "outputs": [ { "internalType": "address", - "name": "recipient_", + "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newMinWithdrawalAmount", + "type": "uint256" + } + ], + "name": "setMinWithdrawalAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newRecipient", + "type": "address" + } + ], + "name": "setRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum Types.WithdrawalNetwork", + "name": "_newWithdrawalNetwork", + "type": "uint8" + } + ], + "name": "setWithdrawalNetwork", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "totalProcessed", @@ -141,13 +180,51 @@ "outputs": [ { "internalType": "enum Types.WithdrawalNetwork", - "name": "network_", + "name": "", "type": "uint8" } ], "stateMutability": "view", "type": "function" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldWithdrawalAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newWithdrawalAmount", + "type": "uint256" + } + ], + "name": "MinWithdrawalAmountUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldRecipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newRecipient", + "type": "address" + } + ], + "name": "RecipientUpdated", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -203,5 +280,29 @@ ], "name": "Withdrawal", "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "enum Types.WithdrawalNetwork", + "name": "oldWithdrawalNetwork", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum Types.WithdrawalNetwork", + "name": "newWithdrawalNetwork", + "type": "uint8" + } + ], + "name": "WithdrawalNetworkUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "FeeSplitter_OnlyProxyAdminOwner", + "type": "error" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/SuperchainRevSharesCalculator.json b/packages/contracts-bedrock/snapshots/abi/SuperchainRevSharesCalculator.json new file mode 100644 index 00000000000..a671b3bbaee --- /dev/null +++ b/packages/contracts-bedrock/snapshots/abi/SuperchainRevSharesCalculator.json @@ -0,0 +1,231 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "BASIS_POINT_SCALE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GROSS_SHARE_BPS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NET_SHARE_BPS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_sequencerFeeRevenue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_baseFeeRevenue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_operatorFeeRevenue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_l1FeeRevenue", + "type": "uint256" + } + ], + "name": "getRecipientsAndValues", + "outputs": [ + { + "components": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "internalType": "struct ShareInfo[]", + "name": "shareInfo", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_shareRecipient", + "type": "address" + }, + { + "internalType": "address payable", + "name": "_remainderRecipient", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "remainderRecipient", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_remainderRecipient", + "type": "address" + } + ], + "name": "setRemainderRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_shareRecipient", + "type": "address" + } + ], + "name": "setShareRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shareRecipient", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "remainderRecipient", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "oldRemainderRecipient", + "type": "address" + } + ], + "name": "RemainderRecipientUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "shareRecipient", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "oldSHareRecipient", + "type": "address" + } + ], + "name": "ShareRecipientUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "SharesCalculator_OnlyProxyAdminOwner", + "type": "error" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index ee9789f5799..4670b7f79fb 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -44,8 +44,8 @@ "sourceCodeHash": "0x997212ceadabb306c2abd31918b09bccbba0b21662c1d8930a3599831c374b13" }, "src/L2/BaseFeeVault.sol:BaseFeeVault": { - "initCodeHash": "0x9b664e3d84ad510091337b4aacaa494b142512e2f6f7fbcdb6210ed62ca9b885", - "sourceCodeHash": "0x508610081cade08f935e2a66f31cc193874bc0e2971a65db4a7842f1a428b1d0" + "initCodeHash": "0xe68cf9422671396ab876cdae71ddfa634a511b8400fa784f466bec380ce4aa84", + "sourceCodeHash": "0x2e3673e0b592204ef30dc58d44c66d6587c8efe5fb5aeaf1a3a757343d06d09f" }, "src/L2/CrossL2Inbox.sol:CrossL2Inbox": { "initCodeHash": "0x56f868e561c4abe539043f98b16aad9305479e68fd03ece2233249b0c73a24ea", @@ -56,8 +56,12 @@ "sourceCodeHash": "0x6d137fef431d75a8bf818444915fc39c8b1d93434a9af9971d96fb3170bc72b7" }, "src/L2/FeeSplitter.sol:FeeSplitter": { - "initCodeHash": "0x38c00e0b26d664be3e2976bb93ef908fb186e80a0f4432737dd98c7a2061db8c", - "sourceCodeHash": "0x7e1b063c20074c8085d427e031353af72b3cb570c724d203b39f33d52434d7f8" + "initCodeHash": "0x0795a2d9e353f98750997c7475be9bac693105d2f361c669a10b0fd5826c0efb", + "sourceCodeHash": "0xe2f567d995f6abecfb92a64a57894caabfdfa81c803e555cce1e2ab2e7713e83" + }, + "src/L2/FeeVaultInitializer.sol:FeeVaultInitializer": { + "initCodeHash": "0x453a28d8c3ef30a99ed18163ac7a49e57138545470b5de78c7fdf0ebce2c1b90", + "sourceCodeHash": "0x51cc656fde167195e8d142d3e95f957f3bbcf2782bbe6b6f975452f009e65d9f" }, "src/L2/GasPriceOracle.sol:GasPriceOracle": { "initCodeHash": "0x38ef70b2783dd45ad807afcf57972c7df4abaaeb5d16d17cdb451b9e931a9cbb", @@ -68,8 +72,8 @@ "sourceCodeHash": "0x6e5349fd781d5f0127ff29ccea4d86a80240550cfa322364183a0f629abcb43e" }, "src/L2/L1FeeVault.sol:L1FeeVault": { - "initCodeHash": "0x9b664e3d84ad510091337b4aacaa494b142512e2f6f7fbcdb6210ed62ca9b885", - "sourceCodeHash": "0xfdf158752a5802c3697d6e8467046f6378680ceaa9e59ab02da0f5dcd575e5e2" + "initCodeHash": "0xe68cf9422671396ab876cdae71ddfa634a511b8400fa784f466bec380ce4aa84", + "sourceCodeHash": "0x2e85139090b9072e368a5ff36e5fcf2a90b219c6024e06a7998904cd75412395" }, "src/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger": { "initCodeHash": "0xe160be403df12709c371c33195d1b9c3b5e9499e902e86bdabc8eed749c3fd61", @@ -96,8 +100,8 @@ "sourceCodeHash": "0xbea4229c5c6988243dbc7cf5a086ddd412fe1f2903b8e20d56699fec8de0c2c9" }, "src/L2/OperatorFeeVault.sol:OperatorFeeVault": { - "initCodeHash": "0x3d8c0d7736e8767f2f797da1c20c5fe30bd7f48a4cf75f376290481ad7c0f91f", - "sourceCodeHash": "0x2022fdb4e32769eb9446dab4aed4b8abb5261fd866f381cccfa7869df1a2adff" + "initCodeHash": "0xf31c45f2c8918bc048bdb72ba2113b449bc9b7b4fcad67475baee1c8f4d8543c", + "sourceCodeHash": "0xcf6f8ca3a9d093c91722fe15489c6a5566f54dd38f14a82e7e063019e4ea507c" }, "src/L2/OptimismMintableERC721.sol:OptimismMintableERC721": { "initCodeHash": "0x316c6d716358f5b5284cd5457ea9fca4b5ad4a37835d4b4b300413dafbfa2159", @@ -120,8 +124,8 @@ "sourceCodeHash": "0x11b6236911e909ed10d4f194fe7315c1f5533d21cbe69a8ff16248c827df2647" }, "src/L2/SequencerFeeVault.sol:SequencerFeeVault": { - "initCodeHash": "0x96474e1d225513c931b8c5c656541212d659686ddc6d49a72ac4df9d640eedd5", - "sourceCodeHash": "0x7df290a6fbc8e712cf4411c3965fd4c59511477f70e666882c57f7c25cf4523e" + "initCodeHash": "0xf75800910406ecf2320664c5d874dd052f7696bae4cbe659443d6d3c10861259", + "sourceCodeHash": "0x755e5296877de76bb659212acae5980775825c7469c7a4d21f8f75bcdb5fbabd" }, "src/L2/SuperchainERC20.sol:SuperchainERC20": { "initCodeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", @@ -131,6 +135,10 @@ "initCodeHash": "0xa43665ad0f2b4f092ff04b12e38f24aa8d2cb34ae7a06fc037970743547bdf98", "sourceCodeHash": "0x862b8a2e5dd5cafcda55e35df7713b0d0b7a93d4d6ce29ea9ca53e045bf63cb4" }, + "src/L2/SuperchainRevSharesCalculator.sol:SuperchainRevSharesCalculator": { + "initCodeHash": "0x6c280cd93f24b07c4fbf9c84ad0537026390b17cef986cc3d14811c43d76f5c9", + "sourceCodeHash": "0x4090da123ba9484b5016b82236da6e9d5ef258e29eba19beb209e792303206e3" + }, "src/L2/SuperchainTokenBridge.sol:SuperchainTokenBridge": { "initCodeHash": "0xb0d25dc03b9c84b07b263921c2b717e6caad3f4297fa939207e35978d7d25abe", "sourceCodeHash": "0x0ff7c1f0264d784fac5d69b792c6bc9d064d4a09701c1bafa808388685c8c4f1" diff --git a/packages/contracts-bedrock/snapshots/storageLayout/BaseFeeVault.json b/packages/contracts-bedrock/snapshots/storageLayout/BaseFeeVault.json index 93c5a7ec8a6..7342c089512 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/BaseFeeVault.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/BaseFeeVault.json @@ -7,10 +7,38 @@ "type": "uint256" }, { - "bytes": "1536", - "label": "__gap", + "bytes": "32", + "label": "_minWithdrawalAmount", "offset": 0, "slot": "1", - "type": "uint256[48]" + "type": "uint256" + }, + { + "bytes": "20", + "label": "_recipient", + "offset": 0, + "slot": "2", + "type": "address" + }, + { + "bytes": "1", + "label": "_withdrawalNetwork", + "offset": 20, + "slot": "2", + "type": "enum Types.WithdrawalNetwork" + }, + { + "bytes": "1", + "label": "_configFlags", + "offset": 21, + "slot": "2", + "type": "uint8" + }, + { + "bytes": "1408", + "label": "__gap", + "offset": 0, + "slot": "3", + "type": "uint256[44]" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/FeeSplitter.json b/packages/contracts-bedrock/snapshots/storageLayout/FeeSplitter.json index 0419bfc632f..320492f5375 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/FeeSplitter.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/FeeSplitter.json @@ -15,65 +15,30 @@ }, { "bytes": "32", - "label": "_status", + "label": "_revenuePerVault", "offset": 0, "slot": "1", - "type": "uint256" + "type": "mapping(address => uint256)" }, { - "bytes": "32", - "label": "payoutGateState", + "bytes": "20", + "label": "shareCalculator", "offset": 0, "slot": "2", - "type": "uint256" + "type": "contract ISharesCalculator" }, { - "bytes": "20", - "label": "revenueShareRecipient", + "bytes": "16", + "label": "lastDisbursementTime", "offset": 0, "slot": "3", - "type": "address payable" - }, - { - "bytes": "20", - "label": "revenueRemainderRecipient", - "offset": 0, - "slot": "4", - "type": "address payable" + "type": "uint128" }, { - "bytes": "18", - "label": "netFeeRevenue", - "offset": 0, - "slot": "5", - "type": "uint144" - }, - { - "bytes": "5", - "label": "lastDisbursementTime", - "offset": 18, - "slot": "5", - "type": "uint40" - }, - { - "bytes": "2", - "label": "netFeeShareBP", - "offset": 23, - "slot": "5", - "type": "uint16" - }, - { - "bytes": "2", - "label": "grossFeeShareBP", - "offset": 25, - "slot": "5", - "type": "uint16" - }, - { - "bytes": "5", + "bytes": "16", "label": "feeDisbursementInterval", - "offset": 27, - "slot": "5", - "type": "uint40" + "offset": 16, + "slot": "3", + "type": "uint128" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/FeeVaultInitializer.json b/packages/contracts-bedrock/snapshots/storageLayout/FeeVaultInitializer.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/storageLayout/FeeVaultInitializer.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/L1FeeVault.json b/packages/contracts-bedrock/snapshots/storageLayout/L1FeeVault.json index 93c5a7ec8a6..7342c089512 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/L1FeeVault.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/L1FeeVault.json @@ -7,10 +7,38 @@ "type": "uint256" }, { - "bytes": "1536", - "label": "__gap", + "bytes": "32", + "label": "_minWithdrawalAmount", "offset": 0, "slot": "1", - "type": "uint256[48]" + "type": "uint256" + }, + { + "bytes": "20", + "label": "_recipient", + "offset": 0, + "slot": "2", + "type": "address" + }, + { + "bytes": "1", + "label": "_withdrawalNetwork", + "offset": 20, + "slot": "2", + "type": "enum Types.WithdrawalNetwork" + }, + { + "bytes": "1", + "label": "_configFlags", + "offset": 21, + "slot": "2", + "type": "uint8" + }, + { + "bytes": "1408", + "label": "__gap", + "offset": 0, + "slot": "3", + "type": "uint256[44]" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OperatorFeeVault.json b/packages/contracts-bedrock/snapshots/storageLayout/OperatorFeeVault.json index 93c5a7ec8a6..7342c089512 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/OperatorFeeVault.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/OperatorFeeVault.json @@ -7,10 +7,38 @@ "type": "uint256" }, { - "bytes": "1536", - "label": "__gap", + "bytes": "32", + "label": "_minWithdrawalAmount", "offset": 0, "slot": "1", - "type": "uint256[48]" + "type": "uint256" + }, + { + "bytes": "20", + "label": "_recipient", + "offset": 0, + "slot": "2", + "type": "address" + }, + { + "bytes": "1", + "label": "_withdrawalNetwork", + "offset": 20, + "slot": "2", + "type": "enum Types.WithdrawalNetwork" + }, + { + "bytes": "1", + "label": "_configFlags", + "offset": 21, + "slot": "2", + "type": "uint8" + }, + { + "bytes": "1408", + "label": "__gap", + "offset": 0, + "slot": "3", + "type": "uint256[44]" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/SequencerFeeVault.json b/packages/contracts-bedrock/snapshots/storageLayout/SequencerFeeVault.json index 93c5a7ec8a6..7342c089512 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/SequencerFeeVault.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/SequencerFeeVault.json @@ -7,10 +7,38 @@ "type": "uint256" }, { - "bytes": "1536", - "label": "__gap", + "bytes": "32", + "label": "_minWithdrawalAmount", "offset": 0, "slot": "1", - "type": "uint256[48]" + "type": "uint256" + }, + { + "bytes": "20", + "label": "_recipient", + "offset": 0, + "slot": "2", + "type": "address" + }, + { + "bytes": "1", + "label": "_withdrawalNetwork", + "offset": 20, + "slot": "2", + "type": "enum Types.WithdrawalNetwork" + }, + { + "bytes": "1", + "label": "_configFlags", + "offset": 21, + "slot": "2", + "type": "uint8" + }, + { + "bytes": "1408", + "label": "__gap", + "offset": 0, + "slot": "3", + "type": "uint256[44]" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/SuperchainRevSharesCalculator.json b/packages/contracts-bedrock/snapshots/storageLayout/SuperchainRevSharesCalculator.json new file mode 100644 index 00000000000..60a2a2bd137 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/storageLayout/SuperchainRevSharesCalculator.json @@ -0,0 +1,30 @@ +[ + { + "bytes": "1", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "uint8" + }, + { + "bytes": "1", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "bool" + }, + { + "bytes": "20", + "label": "shareRecipient", + "offset": 2, + "slot": "0", + "type": "address payable" + }, + { + "bytes": "20", + "label": "remainderRecipient", + "offset": 0, + "slot": "1", + "type": "address payable" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/src/L2/BaseFeeVault.sol b/packages/contracts-bedrock/src/L2/BaseFeeVault.sol index 91f8e0d93b4..21c171e5fd6 100644 --- a/packages/contracts-bedrock/src/L2/BaseFeeVault.sol +++ b/packages/contracts-bedrock/src/L2/BaseFeeVault.sol @@ -16,8 +16,8 @@ import { ISemver } from "interfaces/universal/ISemver.sol"; /// @notice The BaseFeeVault accumulates the base fee that is paid by transactions. contract BaseFeeVault is FeeVault, ISemver { /// @notice Semantic version. - /// @custom:semver 1.5.1 - string public constant version = "1.5.1"; + /// @custom:semver 1.6.0 + string public constant version = "1.6.0"; /// @notice Constructs the BaseFeeVault contract. /// @param _recipient Wallet that will receive the fees. diff --git a/packages/contracts-bedrock/src/L2/FeeSplitter.sol b/packages/contracts-bedrock/src/L2/FeeSplitter.sol index 6839cd3bc1b..c5623101071 100644 --- a/packages/contracts-bedrock/src/L2/FeeSplitter.sol +++ b/packages/contracts-bedrock/src/L2/FeeSplitter.sol @@ -12,7 +12,6 @@ import { ISemver } from "interfaces/universal/ISemver.sol"; import { ISharesCalculator, ShareInfo } from "interfaces/L2/ISharesCalculator.sol"; import { IFeeVault } from "interfaces/L2/IFeeVault.sol"; - // OpenZeppelin import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; @@ -57,7 +56,8 @@ contract FeeSplitter is ISemver, Initializable { /// @notice Transient storage slot key for disbursement-in-progress flag. /// Equal to bytes32(uint256(keccak256("feesplitter.isDisbursing")) - 1) - bytes32 internal constant _FEE_SPLITTER_IS_DISBURSING_SLOT = 0xe3007e9730850b5618eacb0537bef0cf0f1600267ae8549e472449d77b731e45; + bytes32 internal constant _FEE_SPLITTER_IS_DISBURSING_SLOT = + 0xe3007e9730850b5618eacb0537bef0cf0f1600267ae8549e472449d77b731e45; /// @notice Tracks the revenue received by each vault. mapping(address => uint256) internal _revenuePerVault; @@ -252,4 +252,4 @@ contract FeeSplitter is ISemver, Initializable { isDisbursing_ := tload(_FEE_SPLITTER_IS_DISBURSING_SLOT) } } -} \ No newline at end of file +} diff --git a/packages/contracts-bedrock/src/L2/FeeVault.sol b/packages/contracts-bedrock/src/L2/FeeVault.sol index 86c94fc3f6d..71c090271ae 100644 --- a/packages/contracts-bedrock/src/L2/FeeVault.sol +++ b/packages/contracts-bedrock/src/L2/FeeVault.sol @@ -7,6 +7,7 @@ import { Predeploys } from "src/libraries/Predeploys.sol"; // Interfaces import { IL2ToL1MessagePasser } from "interfaces/L2/IL2ToL1MessagePasser.sol"; +import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol"; // Libraries import { Types } from "src/libraries/Types.sol"; @@ -15,6 +16,9 @@ import { Types } from "src/libraries/Types.sol"; /// @notice The FeeVault contract contains the basic logic for the various different vault contracts /// used to hold fee revenue generated by the L2 system. abstract contract FeeVault { + /// @notice Error thrown when a function meant to be called by the ProxyAdmin owner is called by another account. + error FeeSplitter_OnlyProxyAdminOwner(); + /// @notice Minimum balance before a withdrawal can be triggered. /// Use the `minWithdrawalAmount()` getter as this is deprecated /// and is subject to be removed in the future. @@ -36,11 +40,29 @@ abstract contract FeeVault { /// @notice The minimum gas limit for the FeeVault withdrawal transaction. uint32 internal constant WITHDRAWAL_MIN_GAS = 400_000; + /// @notice Flag positions for configuration tracking. + uint8 internal constant RECIPIENT_FLAG = 0; + uint8 internal constant MIN_WITHDRAWAL_AMOUNT_FLAG = 1; + uint8 internal constant WITHDRAWAL_NETWORK_FLAG = 2; + /// @notice Total amount of wei processed by the contract. uint256 public totalProcessed; - /// @notice Reserve extra slots in the storage layout for future upgrades. - uint256[48] private __gap; + /// @notice Minimum balance before a withdrawal can be triggered. + uint256 internal _minWithdrawalAmount; + + /// @notice Account that will receive the fees. Can be located on L1 or L2. + address internal _recipient; + + /// @notice Network which the recipient will receive fees on. + Types.WithdrawalNetwork internal _withdrawalNetwork; + + /// @notice Configuration flags to track which values have been set by the owner. + /// @dev Bit 0: ownerSetRecipient, Bit 1: ownerSetMinWithdrawalAmount, Bit 2: ownerSetWithdrawalNetwork + uint8 private _configFlags; + + /// @notice Reserve extra slots in the storage layout for future upgrades, 50 in total. + uint256[46] private __gap; /// @notice Emitted each time a withdrawal occurs. This event will be deprecated /// in favor of the Withdrawal event containing the WithdrawalNetwork parameter. @@ -56,6 +78,23 @@ abstract contract FeeVault { /// @param withdrawalNetwork Network which the to address will receive funds on. event Withdrawal(uint256 value, address to, address from, Types.WithdrawalNetwork withdrawalNetwork); + /// @notice Emitted when the minimum withdrawal amount for the vault is updated. + /// @param oldWithdrawalAmount The previous minimum withdrawal amount. + /// @param newWithdrawalAmount The new minimum withdrawal amount. + event MinWithdrawalAmountUpdated(uint256 oldWithdrawalAmount, uint256 newWithdrawalAmount); + + /// @notice Emitted when the fee recipient for this vault is updated. + /// @param oldRecipient The previous recipient address. + /// @param newRecipient The new recipient address. + event RecipientUpdated(address oldRecipient, address newRecipient); + + /// @notice Emitted when the withdrawal network for this vault is updated. + /// @param oldWithdrawalNetwork The previous withdrawal network. + /// @param newWithdrawalNetwork The new withdrawal network. + event WithdrawalNetworkUpdated( + Types.WithdrawalNetwork oldWithdrawalNetwork, Types.WithdrawalNetwork newWithdrawalNetwork + ); + /// @param _recipient Wallet that will receive the fees. /// @param _minWithdrawalAmount Minimum balance for withdrawals. /// @param _withdrawalNetwork Network which the recipient will receive fees on. @@ -65,46 +104,122 @@ abstract contract FeeVault { WITHDRAWAL_NETWORK = _withdrawalNetwork; } + /// @notice Sets a configuration flag to indicate a value has been set by the owner. + /// @param flagPosition The bit position of the flag to set. + function _setConfigFlag(uint8 flagPosition) internal { + _configFlags |= uint8(1 << flagPosition); + } + + /// @notice Checks if a configuration flag is set. + /// @param flagPosition The bit position of the flag to check. + /// @return True if the flag is set, false otherwise. + function _isConfigFlagSet(uint8 flagPosition) internal view returns (bool) { + return (_configFlags & uint8(1 << flagPosition)) != 0; + } + /// @notice Allow the contract to receive ETH. receive() external payable { } - /// @notice Minimum balance before a withdrawal can be triggered. - function minWithdrawalAmount() public view returns (uint256 amount_) { - amount_ = MIN_WITHDRAWAL_AMOUNT; + /// @notice Updates the minimum amount of funds the SequencerFeeVault contract must hold before they can be + /// withdrawn. + /// @param _newMinWithdrawalAmount The new minimum withdrawal amount. + function setMinWithdrawalAmount(uint256 _newMinWithdrawalAmount) external { + if (msg.sender != IProxyAdmin(Predeploys.PROXY_ADMIN).owner()) { + revert FeeSplitter_OnlyProxyAdminOwner(); + } + + uint256 oldWithdrawalAmount = _minWithdrawalAmount; + _minWithdrawalAmount = _newMinWithdrawalAmount; + _setConfigFlag(MIN_WITHDRAWAL_AMOUNT_FLAG); + + emit MinWithdrawalAmountUpdated(oldWithdrawalAmount, _newMinWithdrawalAmount); } - /// @notice Account that will receive the fees. Can be located on L1 or L2. - function recipient() public view returns (address recipient_) { - recipient_ = RECIPIENT; + /// @notice Updates the recipient of sequencer fees when they are withdrawn from the vault. + /// @param _newRecipient The new recipient address. + function setRecipient(address _newRecipient) external { + if (msg.sender != IProxyAdmin(Predeploys.PROXY_ADMIN).owner()) { + revert FeeSplitter_OnlyProxyAdminOwner(); + } + + address oldRecipient = _recipient; + _recipient = _newRecipient; + _setConfigFlag(RECIPIENT_FLAG); + + emit RecipientUpdated(oldRecipient, _newRecipient); } - /// @notice Network which the recipient will receive fees on. - function withdrawalNetwork() public view returns (Types.WithdrawalNetwork network_) { - network_ = WITHDRAWAL_NETWORK; + /// @notice Updates the network to which sequencer fees will be withdrawn. This can be either WithdrawalNetwork.L1 + /// to withdraw them to an address on L1 by using the L2ToL1MessagePasser predeploy, or WithdrawalNetwork.L2 to + /// withdraw them to an address on the same chain. + /// @param _newWithdrawalNetwork The new withdrawal network. + function setWithdrawalNetwork(Types.WithdrawalNetwork _newWithdrawalNetwork) external { + if (msg.sender != IProxyAdmin(Predeploys.PROXY_ADMIN).owner()) { + revert FeeSplitter_OnlyProxyAdminOwner(); + } + + Types.WithdrawalNetwork oldWithdrawalNetwork = _withdrawalNetwork; + _withdrawalNetwork = _newWithdrawalNetwork; + _setConfigFlag(WITHDRAWAL_NETWORK_FLAG); + + emit WithdrawalNetworkUpdated(oldWithdrawalNetwork, _newWithdrawalNetwork); } /// @notice Triggers a withdrawal of funds to the fee wallet on L1 or L2. function withdraw() external { require( - address(this).balance >= MIN_WITHDRAWAL_AMOUNT, + address(this).balance >= minWithdrawalAmount(), "FeeVault: withdrawal amount must be greater than minimum withdrawal amount" ); uint256 value = address(this).balance; totalProcessed += value; - emit Withdrawal(value, RECIPIENT, msg.sender); - emit Withdrawal(value, RECIPIENT, msg.sender, WITHDRAWAL_NETWORK); + emit Withdrawal(value, recipient(), msg.sender); + emit Withdrawal(value, recipient(), msg.sender, withdrawalNetwork()); - if (WITHDRAWAL_NETWORK == Types.WithdrawalNetwork.L2) { - bool success = SafeCall.send(RECIPIENT, value); + if (withdrawalNetwork() == Types.WithdrawalNetwork.L2) { + bool success = SafeCall.send(recipient(), value); require(success, "FeeVault: failed to send ETH to L2 fee recipient"); } else { IL2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER)).initiateWithdrawal{ value: value }({ - _target: RECIPIENT, + _target: recipient(), _gasLimit: WITHDRAWAL_MIN_GAS, _data: hex"" }); } } + + /// @notice Returns the minimum withdrawal amount for the vault. + /// @return The minimum withdrawal amount. + function minWithdrawalAmount() public view returns (uint256) { + if (_isConfigFlagSet(MIN_WITHDRAWAL_AMOUNT_FLAG)) { + // If the flag is set, use the storage variable + return _minWithdrawalAmount; + } + // If the flag is not set, use the immutable + return MIN_WITHDRAWAL_AMOUNT; + } + + /// @notice Returns the recipient of the fees. + /// @return The recipient address. + function recipient() public view returns (address) { + if (_isConfigFlagSet(RECIPIENT_FLAG)) { + // If the flag is set, use the storage variable + return _recipient; + } + // If the flag is not set, use the immutable + return RECIPIENT; + } + + /// @notice Returns the withdrawal network for the vault. + /// @return The withdrawal network. + function withdrawalNetwork() public view returns (Types.WithdrawalNetwork) { + if (_isConfigFlagSet(WITHDRAWAL_NETWORK_FLAG)) { + // If the flag is set, use the storage variable + return _withdrawalNetwork; + } + // If the flag is not set, use the immutable + return WITHDRAWAL_NETWORK; + } } diff --git a/packages/contracts-bedrock/src/L2/FeeVaultInitializer.sol b/packages/contracts-bedrock/src/L2/FeeVaultInitializer.sol new file mode 100644 index 00000000000..c9f131cf5d5 --- /dev/null +++ b/packages/contracts-bedrock/src/L2/FeeVaultInitializer.sol @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { BaseFeeVault } from "src/L2/BaseFeeVault.sol"; +import { SequencerFeeVault } from "src/L2/SequencerFeeVault.sol"; +import { L1FeeVault } from "src/L2/L1FeeVault.sol"; +import { OperatorFeeVault } from "src/L2/OperatorFeeVault.sol"; + +// Libraries +import { Types } from "src/libraries/Types.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; + +// Interfaces +import { ISemver } from "interfaces/universal/ISemver.sol"; +import { IFeeVault } from "interfaces/L2/IFeeVault.sol"; + +/// @title FeeVaultInitializer +/// @notice This contract deploys new fee vault implementations with current configurations as immutables. +/// It reads the current configuration from existing fee vault proxies and deploys new implementations +/// with those values set as immutable parameters, ensuring consistent behavior across deployments. +contract FeeVaultInitializer is ISemver { + /// @notice Semantic version. + /// @custom:semver 1.0.0 + string public constant version = "1.0.0"; + + /// @notice Emitted when a fee vault implementation is deployed. + /// @param vaultType The type of fee vault being deployed. + /// @param newImplementation The deployed implementation address. + /// @param recipient The recipient address for the implementation. + /// @param network The withdrawal network for the implementation. + /// @param minWithdrawalAmount The minimum withdrawal amount for the implementation. + event FeeVaultDeployed( + string indexed vaultType, + address indexed newImplementation, + address recipient, + Types.WithdrawalNetwork network, + uint256 minWithdrawalAmount + ); + + /// @notice Constructor that deploys new fee vault implementations with current values as immutables. + constructor() { + _deployBaseFeeVault(); + _deploySequencerFeeVault(); + _deployL1FeeVault(); + _deployOperatorFeeVault(); + } + + /// @notice Helper function to get current fee vault configuration. + /// @param _feeVaultAddress The address of the fee vault to get configuration from. + /// @return recipient_ The recipient address. + /// @return network_ The withdrawal network. + /// @return minWithdrawalAmount_ The minimum withdrawal amount. + function _getFeeVaultConfig(address _feeVaultAddress) + internal + view + returns (address recipient_, Types.WithdrawalNetwork network_, uint256 minWithdrawalAmount_) + { + // Make sure to use legacy functions to avoid failure on upgrade. + recipient_ = IFeeVault(payable(_feeVaultAddress)).RECIPIENT(); + minWithdrawalAmount_ = IFeeVault(payable(_feeVaultAddress)).MIN_WITHDRAWAL_AMOUNT(); + // Use low level call to check for WITHDRAWAL_NETWORK, default to L2 if it doesn't exist + (bool success, bytes memory data) = + _feeVaultAddress.staticcall(abi.encodeCall(IFeeVault.WITHDRAWAL_NETWORK, ())); + network_ = + success && data.length >= 32 ? abi.decode(data, (Types.WithdrawalNetwork)) : Types.WithdrawalNetwork.L2; + } + + /// @notice Deploys a new Base Fee Vault implementation with current configuration as immutables. + /// Reads the current configuration from the existing proxy and deploys a new implementation + /// with those values set as immutable parameters. + function _deployBaseFeeVault() internal { + (address recipient, Types.WithdrawalNetwork network, uint256 minWithdrawalAmount) = + _getFeeVaultConfig(Predeploys.BASE_FEE_VAULT); + + // Deploy new implementation with current values as immutables + BaseFeeVault newBaseFeeVault = new BaseFeeVault(recipient, minWithdrawalAmount, network); + + emit FeeVaultDeployed("BaseFeeVault", address(newBaseFeeVault), recipient, network, minWithdrawalAmount); + } + + /// @notice Deploys a new Sequencer Fee Vault implementation with current configuration as immutables. + /// Reads the current configuration from the existing proxy and deploys a new implementation + /// with those values set as immutable parameters. + function _deploySequencerFeeVault() internal { + (address recipient, Types.WithdrawalNetwork network, uint256 minWithdrawalAmount) = + _getFeeVaultConfig(Predeploys.SEQUENCER_FEE_WALLET); + + // Deploy new implementation with current values as immutables + SequencerFeeVault newSequencerFeeVault = new SequencerFeeVault(recipient, minWithdrawalAmount, network); + + emit FeeVaultDeployed( + "SequencerFeeVault", address(newSequencerFeeVault), recipient, network, minWithdrawalAmount + ); + } + + /// @notice Deploys a new L1 Fee Vault implementation with current configuration as immutables. + /// Reads the current configuration from the existing proxy and deploys a new implementation + /// with those values set as immutable parameters. + function _deployL1FeeVault() internal { + (address recipient, Types.WithdrawalNetwork network, uint256 minWithdrawalAmount) = + _getFeeVaultConfig(Predeploys.L1_FEE_VAULT); + + // Deploy new implementation with current values as immutables + L1FeeVault newL1FeeVault = new L1FeeVault(recipient, minWithdrawalAmount, network); + + emit FeeVaultDeployed("L1FeeVault", address(newL1FeeVault), recipient, network, minWithdrawalAmount); + } + + /// @notice Deploys a new Operator Fee Vault implementation with current configuration as immutables. + /// Reads the current configuration from the existing proxy and deploys a new implementation + /// with those values set as immutable parameters. + function _deployOperatorFeeVault() internal { + (address recipient, Types.WithdrawalNetwork network, uint256 minWithdrawalAmount) = + _getFeeVaultConfig(Predeploys.OPERATOR_FEE_VAULT); + + // Deploy new implementation with current values as immutables + OperatorFeeVault newOperatorFeeVault = new OperatorFeeVault(recipient, minWithdrawalAmount, network); + + emit FeeVaultDeployed("OperatorFeeVault", address(newOperatorFeeVault), recipient, network, minWithdrawalAmount); + } +} diff --git a/packages/contracts-bedrock/src/L2/L1FeeVault.sol b/packages/contracts-bedrock/src/L2/L1FeeVault.sol index de1a212b5e9..58a37ea4e30 100644 --- a/packages/contracts-bedrock/src/L2/L1FeeVault.sol +++ b/packages/contracts-bedrock/src/L2/L1FeeVault.sol @@ -16,8 +16,8 @@ import { ISemver } from "interfaces/universal/ISemver.sol"; /// @notice The L1FeeVault accumulates the L1 portion of the transaction fees. contract L1FeeVault is FeeVault, ISemver { /// @notice Semantic version. - /// @custom:semver 1.5.1 - string public constant version = "1.5.1"; + /// @custom:semver 1.6.0 + string public constant version = "1.6.0"; /// @notice Constructs the L1FeeVault contract. /// @param _recipient Wallet that will receive the fees. diff --git a/packages/contracts-bedrock/src/L2/OperatorFeeVault.sol b/packages/contracts-bedrock/src/L2/OperatorFeeVault.sol index b7341824d6f..c888890d2ea 100644 --- a/packages/contracts-bedrock/src/L2/OperatorFeeVault.sol +++ b/packages/contracts-bedrock/src/L2/OperatorFeeVault.sol @@ -6,7 +6,6 @@ import { FeeVault } from "src/L2/FeeVault.sol"; // Libraries import { Types } from "src/libraries/Types.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; // Interfaces import { ISemver } from "interfaces/universal/ISemver.sol"; @@ -17,10 +16,18 @@ import { ISemver } from "interfaces/universal/ISemver.sol"; /// @notice The OperatorFeeVault accumulates the operator portion of the transaction fees. contract OperatorFeeVault is FeeVault, ISemver { /// @notice Semantic version. - /// @custom:semver 1.0.0 - string public constant version = "1.0.0"; + /// @custom:semver 1.1.0 + string public constant version = "1.1.0"; /// @notice Constructs the OperatorFeeVault contract. - /// Funds are withdrawn to the base fee vault on the L2 network. - constructor() FeeVault(Predeploys.BASE_FEE_VAULT, 0, Types.WithdrawalNetwork.L2) { } + /// @param _recipient Wallet that will receive the fees. + /// @param _minWithdrawalAmount Minimum balance for withdrawals. + /// @param _withdrawalNetwork Network which the recipient will receive fees on. + constructor( + address _recipient, + uint256 _minWithdrawalAmount, + Types.WithdrawalNetwork _withdrawalNetwork + ) + FeeVault(_recipient, _minWithdrawalAmount, _withdrawalNetwork) + { } } diff --git a/packages/contracts-bedrock/src/L2/SequencerFeeVault.sol b/packages/contracts-bedrock/src/L2/SequencerFeeVault.sol index 0b4401deed4..cef66410156 100644 --- a/packages/contracts-bedrock/src/L2/SequencerFeeVault.sol +++ b/packages/contracts-bedrock/src/L2/SequencerFeeVault.sol @@ -16,8 +16,8 @@ import { ISemver } from "interfaces/universal/ISemver.sol"; /// @notice The SequencerFeeVault is the contract that holds any fees paid to the Sequencer during /// transaction processing and block production. contract SequencerFeeVault is FeeVault, ISemver { - /// @custom:semver 1.5.1 - string public constant version = "1.5.1"; + /// @custom:semver 1.6.0 + string public constant version = "1.6.0"; /// @notice Constructs the SequencerFeeVault contract. /// @param _recipient Wallet that will receive the fees. @@ -35,6 +35,6 @@ contract SequencerFeeVault is FeeVault, ISemver { /// @notice Legacy getter for the recipient address. /// @return The recipient address. function l1FeeWallet() public view returns (address) { - return RECIPIENT; + return recipient(); } } diff --git a/packages/contracts-bedrock/src/L2/SuperchainRevSharesCalculator.sol b/packages/contracts-bedrock/src/L2/SuperchainRevSharesCalculator.sol index 221373802a0..1ac73cc2005 100644 --- a/packages/contracts-bedrock/src/L2/SuperchainRevSharesCalculator.sol +++ b/packages/contracts-bedrock/src/L2/SuperchainRevSharesCalculator.sol @@ -14,8 +14,8 @@ import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/I /// @custom:proxied /// @title SuperchainRevSharesCalculator -/// @notice Calculator for Superchain revenue share. It pays the greater amount between 2.5% of -/// gross revenue or 15% of net revenue (gross minus L1 fees) to the configured share recipient. +/// @notice Calculator for Superchain revenue share. It pays the greater amount between 2.5% of +/// gross revenue or 15% of net revenue (gross minus L1 fees) to the configured share recipient. /// The second configured recipient receives the full remainder via FeeSplitter's remainder send. contract SuperchainRevSharesCalculator is ISemver, Initializable { /// @notice Emitted when the share recipient is updated. @@ -56,13 +56,7 @@ contract SuperchainRevSharesCalculator is ISemver, Initializable { /// @notice Initializes the contract with an initial configuration. /// @param _shareRecipient Recipient of the Superchain revenue share. /// @param _remainderRecipient Recipient of the remainder. - function initialize( - address payable _shareRecipient, - address payable _remainderRecipient - ) - external - initializer - { + function initialize(address payable _shareRecipient, address payable _remainderRecipient) external initializer { shareRecipient = _shareRecipient; remainderRecipient = _remainderRecipient; } @@ -125,4 +119,4 @@ contract SuperchainRevSharesCalculator is ISemver, Initializable { remainderRecipient = _remainderRecipient; emit RemainderRecipientUpdated(_remainderRecipient, oldRemainderRecipient); } -} \ No newline at end of file +} diff --git a/packages/contracts-bedrock/test/L2/FeeSplitter.t.sol b/packages/contracts-bedrock/test/L2/FeeSplitter.t.sol index 2a93ffed2dd..783163b5976 100644 --- a/packages/contracts-bedrock/test/L2/FeeSplitter.t.sol +++ b/packages/contracts-bedrock/test/L2/FeeSplitter.t.sol @@ -37,7 +37,7 @@ contract FeeSplitter_TestInit is CommonTest { // Etch the FeeSplitter contract vm.etch(address(feeSplitter), vm.getDeployedCode("FeeSplitter.sol:FeeSplitter")); - + // Get the owner from ProxyAdmin _owner = IProxyAdmin(Predeploys.PROXY_ADMIN).owner(); } @@ -63,7 +63,9 @@ contract FeeSplitter_TestInit is CommonTest { uint256 _baseBalance, uint256 _l1Balance, uint256 _operatorBalance - ) internal { + ) + internal + { _mockFeeVaultForSuccessfulWithdrawal(Predeploys.SEQUENCER_FEE_WALLET, _sequencerBalance); _mockFeeVaultForSuccessfulWithdrawal(Predeploys.BASE_FEE_VAULT, _baseBalance); _mockFeeVaultForSuccessfulWithdrawal(Predeploys.L1_FEE_VAULT, _l1Balance); @@ -95,8 +97,7 @@ contract FeeSplitter_Initialize_Test is FeeSplitter_TestInit { vm.prank(_owner); IFeeSplitter(payable(impl)).initialize( - ISharesCalculator(address(_defaultSharesCalculator)), - _defaultFeeDisbursementInterval + ISharesCalculator(address(_defaultSharesCalculator)), _defaultFeeDisbursementInterval ); assertEq(address(IFeeSplitter(payable(impl)).sharesCalculator()), address(_defaultSharesCalculator)); @@ -110,10 +111,10 @@ contract FeeSplitter_Receive_Test is FeeSplitter_TestInit { /// @notice Test that receive function reverts when not during disbursement function test_feeSplitterReceive_WhenReceiveWindowIsClosed_Reverts(address _caller, uint256 _amount) public { vm.deal(_caller, _amount); - + vm.prank(_caller); vm.expectRevert(IFeeSplitter.FeeSplitter_ReceiveWindowClosed.selector); - (bool success,) = payable(address(feeSplitter)).call{value: _amount}(""); + (bool success,) = payable(address(feeSplitter)).call{ value: _amount }(""); } /// @notice Test receive function from non-approved vault reverts even during disbursement @@ -127,18 +128,15 @@ contract FeeSplitter_Receive_Test is FeeSplitter_TestInit { // Mock the _isTransientDisbursing() function to return true // This allows us to test the sender validation logic - vm.mockCall( - address(feeSplitter), - abi.encodeWithSignature("_isTransientDisbursing()"), - abi.encode(true) - ); + vm.mockCall(address(feeSplitter), abi.encodeWithSignature("_isTransientDisbursing()"), abi.encode(true)); // Setup disbursement conditions but expect revert from non-approved sender vm.deal(_caller, _amount); - + vm.prank(_caller); - vm.expectRevert(IFeeSplitter.FeeSplitter_SenderNotApprovedVault.selector); // Now we test the actual sender validation - (bool success,) = payable(address(feeSplitter)).call{value: _amount}(""); + vm.expectRevert(IFeeSplitter.FeeSplitter_SenderNotApprovedVault.selector); // Now we test the actual sender + // validation + (bool success,) = payable(address(feeSplitter)).call{ value: _amount }(""); } /// @notice Test receive function works during disbursement from SequencerFeeVault @@ -150,11 +148,11 @@ contract FeeSplitter_Receive_Test is FeeSplitter_TestInit { _mockFeeVaultForSuccessfulWithdrawal(Predeploys.BASE_FEE_VAULT, 0); _mockFeeVaultForSuccessfulWithdrawal(Predeploys.L1_FEE_VAULT, 0); _mockFeeVaultForSuccessfulWithdrawal(Predeploys.OPERATOR_FEE_VAULT, 0); - + // Mock shares calculator to return valid shares ShareInfo[] memory shareInfo = new ShareInfo[](1); shareInfo[0] = ShareInfo(payable(_defaultRevenueShareRecipient), _amount); - + // Get the actual shares calculator from the FeeSplitter address actualSharesCalculator = address(feeSplitter.sharesCalculator()); vm.mockCall( @@ -168,7 +166,7 @@ contract FeeSplitter_Receive_Test is FeeSplitter_TestInit { // Call disburseFees - this will trigger the receive function during withdrawal feeSplitter.disburseFees(); - + // Verify the recipient got the funds (proves receive function worked) assertEq(address(_defaultRevenueShareRecipient).balance, _amount); assertEq(address(feeSplitter).balance, 0); @@ -184,11 +182,11 @@ contract FeeSplitter_Receive_Test is FeeSplitter_TestInit { _mockFeeVaultForSuccessfulWithdrawal(Predeploys.BASE_FEE_VAULT, _amount); _mockFeeVaultForSuccessfulWithdrawal(Predeploys.L1_FEE_VAULT, 0); _mockFeeVaultForSuccessfulWithdrawal(Predeploys.OPERATOR_FEE_VAULT, 0); - + // Mock shares calculator to return valid shares ShareInfo[] memory shareInfo = new ShareInfo[](1); shareInfo[0] = ShareInfo(payable(_defaultRevenueShareRecipient), _amount); - + // Get the actual shares calculator from the FeeSplitter address actualSharesCalculator = address(feeSplitter.sharesCalculator()); vm.mockCall( @@ -202,7 +200,7 @@ contract FeeSplitter_Receive_Test is FeeSplitter_TestInit { // Call disburseFees - this will trigger the receive function during withdrawal feeSplitter.disburseFees(); - + // Verify the recipient got the funds (proves receive function worked) assertEq(address(_defaultRevenueShareRecipient).balance, _amount); assertEq(address(feeSplitter).balance, 0); @@ -218,11 +216,11 @@ contract FeeSplitter_Receive_Test is FeeSplitter_TestInit { _mockFeeVaultForSuccessfulWithdrawal(Predeploys.BASE_FEE_VAULT, 0); _mockFeeVaultForSuccessfulWithdrawal(Predeploys.L1_FEE_VAULT, _amount); _mockFeeVaultForSuccessfulWithdrawal(Predeploys.OPERATOR_FEE_VAULT, 0); - + // Mock shares calculator to return valid shares ShareInfo[] memory shareInfo = new ShareInfo[](1); shareInfo[0] = ShareInfo(payable(_defaultRevenueShareRecipient), _amount); - + // Get the actual shares calculator from the FeeSplitter address actualSharesCalculator = address(feeSplitter.sharesCalculator()); vm.mockCall( @@ -236,7 +234,7 @@ contract FeeSplitter_Receive_Test is FeeSplitter_TestInit { // Call disburseFees - this will trigger the receive function during withdrawal feeSplitter.disburseFees(); - + // Verify the recipient got the funds (proves receive function worked) assertEq(address(_defaultRevenueShareRecipient).balance, _amount); assertEq(address(feeSplitter).balance, 0); @@ -252,11 +250,11 @@ contract FeeSplitter_Receive_Test is FeeSplitter_TestInit { _mockFeeVaultForSuccessfulWithdrawal(Predeploys.BASE_FEE_VAULT, 0); _mockFeeVaultForSuccessfulWithdrawal(Predeploys.L1_FEE_VAULT, 0); _mockFeeVaultForSuccessfulWithdrawal(Predeploys.OPERATOR_FEE_VAULT, _amount); - + // Mock shares calculator to return valid shares ShareInfo[] memory shareInfo = new ShareInfo[](1); shareInfo[0] = ShareInfo(payable(_defaultRevenueShareRecipient), _amount); - + // Get the actual shares calculator from the FeeSplitter address actualSharesCalculator = address(feeSplitter.sharesCalculator()); vm.mockCall( @@ -270,15 +268,15 @@ contract FeeSplitter_Receive_Test is FeeSplitter_TestInit { // Call disburseFees - this will trigger the receive function during withdrawal feeSplitter.disburseFees(); - + // Verify the recipient got the funds (proves receive function worked) assertEq(address(_defaultRevenueShareRecipient).balance, _amount); assertEq(address(feeSplitter).balance, 0); assertEq(feeSplitter.lastDisbursementTime(), block.timestamp); - } + } } -/// @title FeeSplitter_DisburseFees_Test +/// @title FeeSplitter_DisburseFees_Test /// @notice Tests the disburseFees function of the `FeeSplitter` contract. contract FeeSplitter_DisburseFees_Test is FeeSplitter_TestInit { /// @notice Test disburseFees reverts when interval not reached @@ -293,7 +291,7 @@ contract FeeSplitter_DisburseFees_Test is FeeSplitter_TestInit { /// @notice Test disburseFees reverts when no fees collected function test_feeSplitterDisburseFees_WhenNoFeesCollected_Reverts() public { _setupStandardFeeVaultMocks(0, 0, 0, 0); - + vm.warp(block.timestamp + 25 hours); vm.expectRevert(IFeeSplitter.FeeSplitter_NoFeesCollected.selector); feeSplitter.disburseFees(); @@ -302,8 +300,12 @@ contract FeeSplitter_DisburseFees_Test is FeeSplitter_TestInit { /// @notice Test disburseFees fails when fee vault has wrong withdrawal network function test_feeSplitterDisburseFees_WhenFeeVaultWrongNetwork_Reverts() public { // Mock fee vault with L1 withdrawal network (invalid) - vm.mockCall(Predeploys.SEQUENCER_FEE_WALLET, abi.encodeCall(IFeeVault.withdrawalNetwork, ()), abi.encode(Types.WithdrawalNetwork.L1)); - + vm.mockCall( + Predeploys.SEQUENCER_FEE_WALLET, + abi.encodeCall(IFeeVault.withdrawalNetwork, ()), + abi.encode(Types.WithdrawalNetwork.L1) + ); + vm.warp(block.timestamp + 25 hours); vm.expectRevert(IFeeSplitter.FeeSplitter_FeeVaultMustWithdrawToL2.selector); feeSplitter.disburseFees(); @@ -312,9 +314,15 @@ contract FeeSplitter_DisburseFees_Test is FeeSplitter_TestInit { /// @notice Test disburseFees fails when fee vault has wrong recipient function test_feeSplitterDisburseFees_WhenFeeVaultWrongRecipient_Reverts() public { // Mock fee vault with wrong recipient - vm.mockCall(Predeploys.SEQUENCER_FEE_WALLET, abi.encodeCall(IFeeVault.withdrawalNetwork, ()), abi.encode(Types.WithdrawalNetwork.L2)); - vm.mockCall(Predeploys.SEQUENCER_FEE_WALLET, abi.encodeCall(IFeeVault.recipient, ()), abi.encode(address(0x123))); - + vm.mockCall( + Predeploys.SEQUENCER_FEE_WALLET, + abi.encodeCall(IFeeVault.withdrawalNetwork, ()), + abi.encode(Types.WithdrawalNetwork.L2) + ); + vm.mockCall( + Predeploys.SEQUENCER_FEE_WALLET, abi.encodeCall(IFeeVault.recipient, ()), abi.encode(address(0x123)) + ); + vm.warp(block.timestamp + 25 hours); vm.expectRevert(IFeeSplitter.FeeSplitter_FeeVaultMustWithdrawToFeeSplitter.selector); feeSplitter.disburseFees(); @@ -331,18 +339,21 @@ contract FeeSplitter_DisburseFees_Test is FeeSplitter_TestInit { // Calculate expected gross revenue uint256 expectedGrossRevenue = _sequencerAmount + _baseAmount + _l1Amount + _operatorAmount; - + // Setup mock shares calculator to return 50/50 split uint256 halfGrossRevenue = expectedGrossRevenue / 2; ShareInfo[] memory expectedShareInfo = new ShareInfo[](2); expectedShareInfo[0] = ShareInfo(payable(_defaultRevenueShareRecipient), halfGrossRevenue); - expectedShareInfo[1] = ShareInfo(payable(_defaultRevenueRemainderRecipient), expectedGrossRevenue - halfGrossRevenue); - + expectedShareInfo[1] = + ShareInfo(payable(_defaultRevenueRemainderRecipient), expectedGrossRevenue - halfGrossRevenue); + // Get the actual shares calculator from the FeeSplitter address actualSharesCalculator = address(feeSplitter.sharesCalculator()); vm.mockCall( actualSharesCalculator, - abi.encodeCall(ISharesCalculator.getRecipientsAndValues, (_sequencerAmount, _baseAmount, _operatorAmount, _l1Amount)), + abi.encodeCall( + ISharesCalculator.getRecipientsAndValues, (_sequencerAmount, _baseAmount, _operatorAmount, _l1Amount) + ), abi.encode(expectedShareInfo) ); @@ -361,7 +372,10 @@ contract FeeSplitter_DisburseFees_Test is FeeSplitter_TestInit { // Verify recipients received their shares assertEq(address(_defaultRevenueShareRecipient).balance, revenueShareRecipientBalanceBefore + halfGrossRevenue); - assertEq(address(_defaultRevenueRemainderRecipient).balance, revenueRemainderRecipientBalanceBefore + (expectedGrossRevenue - halfGrossRevenue)); + assertEq( + address(_defaultRevenueRemainderRecipient).balance, + revenueRemainderRecipientBalanceBefore + (expectedGrossRevenue - halfGrossRevenue) + ); // Verify the fee vaults have no balance assertEq(address(Predeploys.SEQUENCER_FEE_WALLET).balance, 0); @@ -474,8 +488,8 @@ contract MockFeeVault { emit Withdrawal(value, RECIPIENT, msg.sender, WITHDRAWAL_NETWORK); if (WITHDRAWAL_NETWORK == Types.WithdrawalNetwork.L2) { - (bool success,) = RECIPIENT.call{value: value}(""); + (bool success,) = RECIPIENT.call{ value: value }(""); require(success, "FeeVault: failed to send ETH to L2 fee recipient"); } } -} \ No newline at end of file +}