diff --git a/src/Constants.sol b/src/Constants.sol index 55657bf..b7a7f9f 100644 --- a/src/Constants.sol +++ b/src/Constants.sol @@ -15,3 +15,6 @@ address constant VALIDATOR_MANAGER_ADDRESS = 0x662530000000000000000000000000000 /// @dev The address of the Registrar predeployed contract on Noble. address constant REGISTRAR_ADDRESS = 0x6625300000000000000000000000000000000003; + +/// @dev The address of the FeeDistributor predeployed contract on Noble. +address constant FEE_DISTRIBUTOR_ADDRESS = 0x6625300000000000000000000000000000000004; diff --git a/src/interfaces/IFeeDistributor.sol b/src/interfaces/IFeeDistributor.sol new file mode 100644 index 0000000..0b332e0 --- /dev/null +++ b/src/interfaces/IFeeDistributor.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.13 <0.9.0; + +/// @title IFeeDistributor +/// @notice Interface for the Fee Distributor contract. +interface IFeeDistributor { + // ========================================================================= + // Types + // ========================================================================= + + /// @notice Return struct for recipient information. + struct RecipientInfo { + address recipient; + uint16 bps; + } + + // ========================================================================= + // Events + // ========================================================================= + + /// @notice Emitted when a recipient is added or updated. + /// @param recipient The recipient address. + /// @param bps The new share of fees in basis points. + event RecipientSet(address indexed recipient, uint16 bps); + + /// @notice Emitted when a recipient is removed. + /// @param recipient The recipient address. + event RecipientRemoved(address indexed recipient); + + // ========================================================================= + // Errors + // ========================================================================= + + /// @notice Error when the caller is not authorized. + error Unauthorized(); + + /// @notice Error when zero basis points is provided. + error ZeroBps(); + + /// @notice Error when total basis points exceeds 10,000. + error TotalBpsExceeded(uint16 totalBps); + + /// @notice Error when the recipient does not exist. + error RecipientNotFound(address recipient); + + // ========================================================================= + // Functions + // ========================================================================= + + /// @notice Sets or updates a recipient's share in basis points. + /// @param recipient The address to receive fees. + /// @param bps The share of fees in basis points. + function setRecipient(address recipient, uint16 bps) external; + + /// @notice Removes a recipient from fee distribution. + /// @param recipient The address to remove. + function removeRecipient(address recipient) external; + + /// @notice Distributes the contract's native balance to recipients. + /// @dev Called during block finalization outside of the normal transaction + /// lifecycle. Implementations must not revert. Each recipient receives a + /// portion of the balance according to their configured basis points. Any + /// remainder is sent to the current block proposer's fee recipient address. + function distribute() external; + + /// @notice Returns all current recipients and their basis points. + /// @return recipients The array of recipient addresses and their shares. + function getRecipients() external view returns (RecipientInfo[] memory recipients); +} diff --git a/src/interfaces/IValidatorManager.sol b/src/interfaces/IValidatorManager.sol index 21770b0..cd0c69e 100644 --- a/src/interfaces/IValidatorManager.sol +++ b/src/interfaces/IValidatorManager.sol @@ -16,6 +16,7 @@ interface IValidatorManager { uint32 ip; uint16 port; bytes32 publicKey; + address feeRecipient; bytes32 name; } @@ -23,6 +24,7 @@ interface IValidatorManager { struct ValidatorInfo { uint64 index; bytes32 publicKey; + address feeRecipient; string name; string socketAddress; } @@ -30,6 +32,7 @@ interface IValidatorManager { /// @notice Input struct for genesis validators. struct GenesisValidator { bytes32 publicKey; + address feeRecipient; bytes32 name; uint32 ip; uint16 port; @@ -45,10 +48,16 @@ interface IValidatorManager { /// @notice Emitted when a validator is removed. event ValidatorRemoved(uint64 indexed index, bytes32 indexed publicKey, string name, uint64 epochRemoved); + /// @notice Emitted when a validator's fee recipient is updated. + event FeeRecipientUpdated(bytes32 indexed publicKey, address oldFeeRecipient, address newFeeRecipient); + // ========================================================================= // Errors // ========================================================================= + /// @notice Error when the caller is not authorized. + error Unauthorized(); + /// @notice Error when a validator is already added. error ValidatorAlreadyAdded(bytes32 publicKey); @@ -58,21 +67,34 @@ interface IValidatorManager { /// @notice Error when a validator does not exist. error ValidatorNotFound(bytes32 publicKey); + /// @notice Error when an address is the zero address. + error ZeroAddress(); + // ========================================================================= // Functions // ========================================================================= /// @notice Adds a new validator to the set, applied from the next epoch. /// @param publicKey The validator's public key. + /// @param feeRecipient The address that receives fees on behalf of the validator. /// @param name The validator's name. /// @param ip The validator's IPv4 address. /// @param port The validator's port. - function addValidator(bytes32 publicKey, bytes32 name, uint32 ip, uint16 port) external; + function addValidator(bytes32 publicKey, address feeRecipient, bytes32 name, uint32 ip, uint16 port) external; /// @notice Removes a validator from the set, applied from the next epoch. /// @param publicKey The validator's public key. function removeValidator(bytes32 publicKey) external; + /// @notice Updates the fee recipient address for a validator. + /// @param publicKey The validator's public key. + /// @param feeRecipient The new address that receives fees on behalf of the validator. + function setFeeRecipient(bytes32 publicKey, address feeRecipient) external; + + /// @notice Returns the fee recipient address for a validator. + /// @param publicKey The validator's public key. + function getFeeRecipient(bytes32 publicKey) external view returns (address); + /// @notice Returns validators active in the current epoch. function getCurrentValidators() external view returns (ValidatorInfo[] memory);