// SPDX-License-Identifier: MIT // MIT License // Copyright (c) 2022 Optimism // Copyright (c) 2022 Scroll // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. pragma solidity =0.8.24; import {IL2ScrollMessenger} from "../IL2ScrollMessenger.sol"; import {OwnableBase} from "../../libraries/common/OwnableBase.sol"; // solhint-disable no-empty-blocks // solhint-disable reason-string /// @title L2TxFeeVault /// @notice The L2TxFeeVault contract contains the logic for the vault contracts /// used to hold fee revenue generated by the L2 system. contract L2TxFeeVault is OwnableBase { /********** * Events * **********/ /// @notice Emits each time that a withdrawal occurs. /// /// @param value Amount that was withdrawn (in wei). /// @param to Address that the funds were sent to. /// @param from Address that triggered the withdrawal. event Withdrawal(uint256 value, address to, address from); /// @notice Emits each time the owner updates the address of `messenger`. /// @param oldMessenger The address of old messenger. /// @param newMessenger The address of new messenger. event UpdateMessenger(address indexed oldMessenger, address indexed newMessenger); /// @notice Emits each time the owner updates the address of `recipient`. /// @param oldRecipient The address of old recipient. /// @param newRecipient The address of new recipient. event UpdateRecipient(address indexed oldRecipient, address indexed newRecipient); /// @notice Emits each time the owner updates the value of `minWithdrawAmount`. /// @param oldMinWithdrawAmount The value of old `minWithdrawAmount`. /// @param newMinWithdrawAmount The value of new `minWithdrawAmount`. event UpdateMinWithdrawAmount(uint256 oldMinWithdrawAmount, uint256 newMinWithdrawAmount); /************* * Variables * *************/ /// @notice Minimum balance before a withdrawal can be triggered. uint256 public minWithdrawAmount; /// @notice Scroll L2 messenger address. address public messenger; /// @notice Wallet that will receive the fees on L1. address public recipient; /// @notice Total amount of wei processed by the contract. uint256 public totalProcessed; /*************** * Constructor * ***************/ /// @param _owner The owner of the contract. /// @param _recipient Wallet that will receive the fees on L1. /// @param _minWithdrawalAmount Minimum balance before a withdrawal can be triggered. constructor( address _owner, address _recipient, uint256 _minWithdrawalAmount ) { _transferOwnership(_owner); minWithdrawAmount = _minWithdrawalAmount; recipient = _recipient; } /***************************** * Public Mutating Functions * *****************************/ /// @notice Allow the contract to receive ETH. receive() external payable {} /// @notice Triggers a withdrawal of funds to the L1 fee wallet. /// @param _value The amount of ETH to withdraw. function withdraw(uint256 _value) public { require( _value >= minWithdrawAmount, "FeeVault: withdrawal amount must be greater than minimum withdrawal amount" ); uint256 _balance = address(this).balance; require(_value <= _balance, "FeeVault: insufficient balance to withdraw"); unchecked { totalProcessed += _value; } emit Withdrawal(_value, recipient, msg.sender); // no fee provided IL2ScrollMessenger(messenger).sendMessage{value: _value}( recipient, _value, bytes(""), // no message (simple eth transfer) 0 // _gasLimit can be zero for fee vault. ); } /// @notice Triggers a withdrawal of all available funds to the L1 fee wallet. function withdraw() external { uint256 value = address(this).balance; withdraw(value); } /************************ * Restricted Functions * ************************/ /// @notice Update the address of messenger. /// @param _newMessenger The address of messenger to update. function updateMessenger(address _newMessenger) external onlyOwner { address _oldMessenger = messenger; messenger = _newMessenger; emit UpdateMessenger(_oldMessenger, _newMessenger); } /// @notice Update the address of recipient. /// @param _newRecipient The address of recipient to update. function updateRecipient(address _newRecipient) external onlyOwner { address _oldRecipient = recipient; recipient = _newRecipient; emit UpdateRecipient(_oldRecipient, _newRecipient); } /// @notice Update the minimum withdraw amount. /// @param _newMinWithdrawAmount The minimum withdraw amount to update. function updateMinWithdrawAmount(uint256 _newMinWithdrawAmount) external onlyOwner { uint256 _oldMinWithdrawAmount = minWithdrawAmount; minWithdrawAmount = _newMinWithdrawAmount; emit UpdateMinWithdrawAmount(_oldMinWithdrawAmount, _newMinWithdrawAmount); } }