RevenueDistributionModule

Description:

Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "src/modules/RevenueDistributionModule.sol": {
      "content": "// SPDX-License-Identifier: Apache-2.0

pragma solidity 0.8.20;

import {PausableUpgradeable} from "openzeppelin-contracts-upgradeable/utils/PausableUpgradeable.sol";
import {IERC20} from "openzeppelin-contracts/token/ERC20/IERC20.sol";
import {Math} from "openzeppelin-contracts/utils/math/Math.sol";
import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";

import {IRevenueDistributionModule} from "src/interfaces/modules/IRevenueDistributionModule.sol";
import {IRegistryContract} from "src/interfaces/registry/IRegistryContract.sol";
import {IRegistryAccess} from "src/interfaces/registry/IRegistryAccess.sol";
import {CheckAccessControl} from "src/utils/CheckAccessControl.sol";
import {IEur0} from "src/interfaces/token/IEur0.sol";
import {ISEur0} from "src/interfaces/vaults/ISEur0.sol";
import {
    PAUSING_CONTRACTS_ROLE,
    UNPAUSING_CONTRACTS_ROLE,
    CONTRACT_REGISTRY_ACCESS,
    CONTRACT_EUR0,
    OPERATOR_REVSWITCH_DISTRIBUTOR_ROLE,
    OPERATOR_ACC_DT_DISTRIBUTOR_ROLE,
    OPERATOR_REB_DT_DISTRIBUTOR_ROLE,
    INITIAL_REVENUE_DISTRIBUTION_MINT_CAP,
    OPERATOR_ADMIN_ROLE,
    ONE_DAY,
    ONE_WEEK,
    BASIS_MILLION_POINT_BASE
} from "src/constants.sol";
import {
    NullAddress,
    DistributionToRebasingDTDisabled,
    DistributionToAccruingDTDisabled,
    DistributionToRevenueSwitchDisabled,
    CannotDistributeEUR0ToRebasingDTMoreThanOnceADay,
    CannotDistributeEUR0ToAccruingDTMoreThanOnceADay,
    CannotDistributeEUR0ToRevenueSwitchMoreThanOnceAWeek,
    NullContract,
    SameValue,
    AmountIsZero,
    InsufficientSupply,
    AmountTooBig,
    MaxDailyAccruingMintAmount,
    MaxDailyRebasingDTMintAmount,
    MaxWeeklyRevSwitchMintAmount
} from "src/errors.sol";

/// @title RevenueDistributionModule
/// @notice Contract for automated minting and distribution of EUR0 tokens to three dedicated buckets
/// @dev This contract enables multipurpose revenue distribution with three fixed buckets:
///      1. Revenue Switch
///      2. Accruing Deposit Token
///      3. Rebasing Deposit Token
/// @author Usual Labs
contract RevenueDistributionModule is PausableUpgradeable, IRevenueDistributionModule {
    using CheckAccessControl for IRegistryAccess;
    using SafeERC20 for IERC20;
    using Math for uint256;

    /*//////////////////////////////////////////////////////////////
                                STORAGE
    //////////////////////////////////////////////////////////////*/

    /// @custom:storage-location erc7201:RevenueDistributionModule.storage.v0
    struct RevenueDistributionModuleStorageV0 {
        /// Maximum amount of EUR0 that can be minted (mint cap)
        uint256 operatorMintCap;
        /// Last time revenue switch was distributed (weekly)
        uint256 lastRevenueSwitchDistribution;
        /// Last time accruing deposit token was distributed (daily)
        uint256 lastAccruingDTDistribution;
        /// Last time rebasing distribution token was distributed (daily)
        uint256 lastRebasingDTDistribution;
        /// The daily accruing yield rate in micro basis points (1 = 0.0001%)
        uint256 dailyAccruingYieldRate;
        /// Maximum amount of EUR0 that can be minted for revenue switch
        uint256 maxRevSwitchMintCap;
        /// Maximum amount of EUR0 that can be minted for accruing deposit token
        uint256 maxAccruingMintCap;
        /// Maximum amount of EUR0 that can be minted for rebasing distribution token
        uint256 maxRebasingDTMintCap;
        /// The address of the registry access contract
        IRegistryAccess registryAccess;
        /// The address of the EUR0 token contract
        IEur0 eur0;
        /// The address of the reward claim contract for rebasing distribution token
        address rewardClaimForRebasingDT;
        /// The address of the reward claim contract for revenue switch
        address rewardClaimForRevenueSwitch;
        /// The address of the reward claim contract for accruing deposit token
        ISEur0 rewardClaimForAccruingDT;
        /// Whether revenue switch distribution is paused
        bool revenueSwitchDistributionPaused;
        /// Whether accruing deposit token distribution is paused
        bool accruingDTDistributionPaused;
        /// Whether rebasing distribution token distribution is paused
        bool rebasingDTDistributionPaused;
    }

    // keccak256(abi.encode(uint256(keccak256("RevenueDistributionModule.storage.v0")) - 1)) & ~bytes32(uint256(0xff))
    // solhint-disable-next-line
    bytes32 public constant RevenueDistributionModuleStorageV0Location =
        0xe0542bbe30b10bf343060c7e797a9d2f82a63e9ef1d0b27e42754d313c510a00;

    /// @notice Returns the storage struct of the contract
    /// @return $ The storage struct
    function _revenueDistributionModuleStorageV0()
        internal
        pure
        returns (RevenueDistributionModuleStorageV0 storage $)
    {
        bytes32 position = RevenueDistributionModuleStorageV0Location;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            $.slot := position
        }
    }

    /*//////////////////////////////////////////////////////////////
                             Constructor
    //////////////////////////////////////////////////////////////*/

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }

    /*//////////////////////////////////////////////////////////////
                             Initializer
    //////////////////////////////////////////////////////////////*/

    /// @notice Initializes the contract with registry contract and yield module
    /// @param _registryContract Address of the registry contract
    /// @param _rewardClaimForRevenueSwitch Address of the reward claim contract for revenue switch
    /// @param _rewardClaimForAccruingDT Address of the reward claim contract for accruing deposit token
    /// @param _rewardClaimForRebasingDT Address of the reward claim contract for rebasing distribution token
    /// @param _dailyAccruingYieldRate The daily accruing yield rate in micro basis points (1 = 0.0001%)
    /// @param _maxRevSwitchMintCap The maximum amount of EUR0 that can be minted for revenue switch
    /// @param _maxAccruingMintCap The maximum amount of EUR0 that can be minted for accruing deposit token
    /// @param _maxRebasingDTMintCap The maximum amount of EUR0 that can be minted for rebasing distribution token
    // solhint-disable-next-line code-complexity
    function initialize(
        address _registryContract,
        address _rewardClaimForRevenueSwitch,
        address _rewardClaimForAccruingDT,
        address _rewardClaimForRebasingDT,
        uint256 _dailyAccruingYieldRate,
        uint256 _maxRevSwitchMintCap,
        uint256 _maxAccruingMintCap,
        uint256 _maxRebasingDTMintCap
    ) public initializer {
        if (_registryContract == address(0)) {
            revert NullContract();
        }
        if (_rewardClaimForRevenueSwitch == address(0)) {
            revert NullAddress();
        }
        if (_rewardClaimForAccruingDT == address(0)) {
            revert NullAddress();
        }
        if (_rewardClaimForRebasingDT == address(0)) {
            revert NullAddress();
        }
        if (_dailyAccruingYieldRate > BASIS_MILLION_POINT_BASE) {
            revert AmountTooBig();
        }
        if (_maxRevSwitchMintCap == 0) {
            revert AmountIsZero();
        }
        if (_maxAccruingMintCap == 0) {
            revert AmountIsZero();
        }
        if (_maxRebasingDTMintCap == 0) {
            revert AmountIsZero();
        }

        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();

        __Pausable_init_unchained();

        IRegistryContract registryContract = IRegistryContract(_registryContract);
        $.registryAccess = IRegistryAccess(registryContract.getContract(CONTRACT_REGISTRY_ACCESS));
        $.eur0 = IEur0(registryContract.getContract(CONTRACT_EUR0));

        $.rewardClaimForRevenueSwitch = _rewardClaimForRevenueSwitch;
        $.rewardClaimForAccruingDT = ISEur0(_rewardClaimForAccruingDT);
        $.rewardClaimForRebasingDT = _rewardClaimForRebasingDT;
        $.operatorMintCap = INITIAL_REVENUE_DISTRIBUTION_MINT_CAP;
        $.maxRevSwitchMintCap = _maxRevSwitchMintCap;
        $.maxAccruingMintCap = _maxAccruingMintCap;
        $.maxRebasingDTMintCap = _maxRebasingDTMintCap;

        // Initialize the three fixed distribution buckets
        $.lastRevenueSwitchDistribution = block.timestamp;
        $.lastAccruingDTDistribution = block.timestamp;
        $.lastRebasingDTDistribution = block.timestamp;

        $.dailyAccruingYieldRate = _dailyAccruingYieldRate;
    }

    /*//////////////////////////////////////////////////////////////
                                External
    //////////////////////////////////////////////////////////////*/

    /// @inheritdoc IRevenueDistributionModule
    function distributeRevenueSwitch(uint256 amount) external whenNotPaused {
        if (amount == 0) {
            revert AmountIsZero();
        }

        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(OPERATOR_REVSWITCH_DISTRIBUTOR_ROLE);

        // Check if revenue switch distribution is enabled
        if ($.revenueSwitchDistributionPaused) {
            revert DistributionToRevenueSwitchDisabled();
        }

        // Check if it's been at least a week since last distribution
        if (block.timestamp - $.lastRevenueSwitchDistribution < ONE_WEEK) {
            revert CannotDistributeEUR0ToRevenueSwitchMoreThanOnceAWeek(); // Too soon to distribute
        }

        // Check max revenue switch mint cap
        if (amount > $.maxRevSwitchMintCap) {
            revert MaxWeeklyRevSwitchMintAmount();
        }

        // Check mint cap
        if (amount > $.operatorMintCap) {
            revert InsufficientSupply();
        }

        // Reduce mint cap
        $.operatorMintCap -= amount;

        // Update last distribution time
        $.lastRevenueSwitchDistribution = block.timestamp;

        // Mint the amount to the reward claim contract
        $.eur0.mint($.rewardClaimForRevenueSwitch, amount);

        emit RevenueSwitchDistributed(amount, block.timestamp);
    }

    /// @inheritdoc IRevenueDistributionModule
    /// @dev This function isn't subject to the operator mint cap
    function distributeAccruingDT() external whenNotPaused {
        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        // Check if accruing deposit token distribution is enabled
        if ($.accruingDTDistributionPaused) {
            revert DistributionToAccruingDTDisabled();
        }
        $.registryAccess.onlyMatchingRole(OPERATOR_ACC_DT_DISTRIBUTOR_ROLE);

        // calculate the amount to distribute
        uint256 amount = $.rewardClaimForAccruingDT.totalAssets().mulDiv(
            $.dailyAccruingYieldRate, BASIS_MILLION_POINT_BASE, Math.Rounding.Floor
        );

        if (amount == 0) {
            revert AmountIsZero();
        }

        // Check if it's been at least a day since last distribution
        if (block.timestamp - $.lastAccruingDTDistribution < ONE_DAY) {
            revert CannotDistributeEUR0ToAccruingDTMoreThanOnceADay();
        }

        // Check max accruing mint cap
        if (amount > $.maxAccruingMintCap) {
            revert MaxDailyAccruingMintAmount();
        }

        // Update last distribution time
        $.lastAccruingDTDistribution = block.timestamp;

        // Mint the amount to this contract
        $.eur0.mint(address($.rewardClaimForAccruingDT), amount);

        // Start yield distribution
        $.rewardClaimForAccruingDT.startYieldDistribution(
            amount, block.timestamp, block.timestamp + ONE_DAY
        );

        emit AccruingDTDistributed(amount, block.timestamp);
    }

    /// @inheritdoc IRevenueDistributionModule
    function distributeRebasingDT(uint256 amount) external whenNotPaused {
        if (amount == 0) {
            revert AmountIsZero();
        }

        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(OPERATOR_REB_DT_DISTRIBUTOR_ROLE);

        // Check if rebasing deposit token distribution is enabled
        if ($.rebasingDTDistributionPaused) {
            revert DistributionToRebasingDTDisabled();
        }

        // Check if it's been at least a day since last distribution
        if (block.timestamp - $.lastRebasingDTDistribution < ONE_DAY) {
            revert CannotDistributeEUR0ToRebasingDTMoreThanOnceADay();
        }

        // Check max rebasing deposit token mint cap
        if (amount > $.maxRebasingDTMintCap) {
            revert MaxDailyRebasingDTMintAmount();
        }

        // Check mint cap
        if (amount > $.operatorMintCap) {
            revert InsufficientSupply();
        }
        // Reduce mint cap
        $.operatorMintCap -= amount;

        // Update last distribution time
        $.lastRebasingDTDistribution = block.timestamp;

        // Mint the amount to the reward claim contract
        $.eur0.mint($.rewardClaimForRebasingDT, amount);

        emit RebasingDTDistributed(amount, block.timestamp);
    }

    /// @inheritdoc IRevenueDistributionModule
    function setDailyAccruingYieldRate(uint256 newDailyRate) external whenNotPaused {
        if (newDailyRate == 0) {
            revert AmountIsZero();
        }
        if (newDailyRate > BASIS_MILLION_POINT_BASE) {
            revert AmountTooBig();
        }
        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(OPERATOR_ADMIN_ROLE);

        if (newDailyRate == $.dailyAccruingYieldRate) {
            revert SameValue();
        }

        $.dailyAccruingYieldRate = newDailyRate;

        emit DailyAccruingYieldRateUpdated(newDailyRate);
    }

    /// @inheritdoc IRevenueDistributionModule
    function setOperatorMintCap(uint256 newMintCap) external whenNotPaused {
        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(OPERATOR_ADMIN_ROLE);
        uint256 oldMintCap = $.operatorMintCap;

        if (newMintCap == oldMintCap) {
            revert SameValue();
        }

        $.operatorMintCap = newMintCap;

        emit OperatorMintCapUpdated(oldMintCap, newMintCap);
    }

    /// @inheritdoc IRevenueDistributionModule
    function setMaxAccruingMintCap(uint256 newMaxAccruingMintCap) external whenNotPaused {
        if (newMaxAccruingMintCap == 0) {
            revert AmountIsZero();
        }
        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(OPERATOR_ADMIN_ROLE);
        $.maxAccruingMintCap = newMaxAccruingMintCap;
        emit MaxAccruingMintCapUpdated(newMaxAccruingMintCap);
    }

    /// @inheritdoc IRevenueDistributionModule
    function setMaxRebasingDTMintCap(uint256 newMaxRebasingDTMintCap) external whenNotPaused {
        if (newMaxRebasingDTMintCap == 0) {
            revert AmountIsZero();
        }
        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(OPERATOR_ADMIN_ROLE);
        $.maxRebasingDTMintCap = newMaxRebasingDTMintCap;
        emit MaxRebasingDTMintCapUpdated(newMaxRebasingDTMintCap);
    }

    /// @inheritdoc IRevenueDistributionModule
    function setMaxRevSwitchMintCap(uint256 newMaxRevSwitchMintCap) external whenNotPaused {
        if (newMaxRevSwitchMintCap == 0) {
            revert AmountIsZero();
        }
        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(OPERATOR_ADMIN_ROLE);
        $.maxRevSwitchMintCap = newMaxRevSwitchMintCap;
        emit MaxRevSwitchMintCapUpdated(newMaxRevSwitchMintCap);
    }

    /// @inheritdoc IRevenueDistributionModule
    function setRewardClaimForRevenueSwitch(address newRewardClaim) external whenNotPaused {
        if (newRewardClaim == address(0)) {
            revert NullAddress();
        }
        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(OPERATOR_ADMIN_ROLE);

        address oldRewardClaimContract = $.rewardClaimForRevenueSwitch;
        if (oldRewardClaimContract == newRewardClaim) {
            revert SameValue();
        }

        $.rewardClaimForRevenueSwitch = newRewardClaim;
        emit RewardClaimForRevenueSwitchUpdated(oldRewardClaimContract, newRewardClaim);
    }

    /// @inheritdoc IRevenueDistributionModule
    function setRewardClaimForAccruingDT(address newRewardClaim) external whenNotPaused {
        if (newRewardClaim == address(0)) {
            revert NullAddress();
        }
        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(OPERATOR_ADMIN_ROLE);

        address oldRewardClaimContract = address($.rewardClaimForAccruingDT);
        if (oldRewardClaimContract == newRewardClaim) {
            revert SameValue();
        }

        $.rewardClaimForAccruingDT = ISEur0(newRewardClaim);
        emit RewardClaimForAccruingDTUpdated(oldRewardClaimContract, address(newRewardClaim));
    }

    /// @inheritdoc IRevenueDistributionModule
    function setRewardClaimForRebasingDT(address newRewardClaim) external whenNotPaused {
        if (newRewardClaim == address(0)) {
            revert NullAddress();
        }
        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(OPERATOR_ADMIN_ROLE);

        address oldRewardClaimContract = $.rewardClaimForRebasingDT;
        if (oldRewardClaimContract == newRewardClaim) {
            revert SameValue();
        }

        $.rewardClaimForRebasingDT = newRewardClaim;
        emit RewardClaimForRebasingDTUpdated(oldRewardClaimContract, newRewardClaim);
    }

    /// @inheritdoc IRevenueDistributionModule
    function pauseRevenueSwitchDistribution() external {
        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(PAUSING_CONTRACTS_ROLE);

        if ($.revenueSwitchDistributionPaused == true) {
            revert SameValue();
        }

        $.revenueSwitchDistributionPaused = true;
        emit RevenueSwitchDistributionPaused();
    }

    /// @inheritdoc IRevenueDistributionModule
    function pauseAccruingDTDistribution() external {
        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(PAUSING_CONTRACTS_ROLE);

        if ($.accruingDTDistributionPaused == true) {
            revert SameValue();
        }

        $.accruingDTDistributionPaused = true;
        emit AccruingDTDistributionPaused();
    }

    /// @inheritdoc IRevenueDistributionModule
    function pauseRebasingDTDistribution() external {
        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(PAUSING_CONTRACTS_ROLE);

        if ($.rebasingDTDistributionPaused == true) {
            revert SameValue();
        }

        $.rebasingDTDistributionPaused = true;
        emit RebasingDTDistributionPaused();
    }

    /// @inheritdoc IRevenueDistributionModule
    function unpauseRevenueSwitchDistribution() external {
        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(UNPAUSING_CONTRACTS_ROLE);

        if ($.revenueSwitchDistributionPaused == false) {
            revert SameValue();
        }

        $.revenueSwitchDistributionPaused = false;
        emit RevenueSwitchDistributionUnpaused();
    }

    /// @inheritdoc IRevenueDistributionModule
    function unpauseAccruingDTDistribution() external {
        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(UNPAUSING_CONTRACTS_ROLE);

        if ($.accruingDTDistributionPaused == false) {
            revert SameValue();
        }

        $.accruingDTDistributionPaused = false;
        emit AccruingDTDistributionUnpaused();
    }

    /// @inheritdoc IRevenueDistributionModule
    function unpauseRebasingDTDistribution() external {
        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(UNPAUSING_CONTRACTS_ROLE);

        if ($.rebasingDTDistributionPaused == false) {
            revert SameValue();
        }

        $.rebasingDTDistributionPaused = false;
        emit RebasingDTDistributionUnpaused();
    }

    /// @inheritdoc IRevenueDistributionModule
    function pause() external {
        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(PAUSING_CONTRACTS_ROLE);
        _pause();
    }

    /// @inheritdoc IRevenueDistributionModule
    function unpause() external {
        RevenueDistributionModuleStorageV0 storage $ = _revenueDistributionModuleStorageV0();
        $.registryAccess.onlyMatchingRole(UNPAUSING_CONTRACTS_ROLE);
        _unpause();
    }

    /// @inheritdoc IRevenueDistributionModule
    function getOperatorMintCap() external view returns (uint256) {
        return _revenueDistributionModuleStorageV0().operatorMintCap;
    }

    /// @inheritdoc IRevenueDistributionModule
    function getDailyAccruingYieldRate() external view returns (uint256) {
        return _revenueDistributionModuleStorageV0().dailyAccruingYieldRate;
    }

    /// @inheritdoc IRevenueDistributionModule
    function getRewardClaimContractForRevenueSwitch() external view returns (address) {
        return _revenueDistributionModuleStorageV0().rewardClaimForRevenueSwitch;
    }

    /// @inheritdoc IRevenueDistributionModule
    function getRewardClaimContractForAccruingDT() external view returns (address) {
        return address(_revenueDistributionModuleStorageV0().rewardClaimForAccruingDT);
    }

    /// @inheritdoc IRevenueDistributionModule
    function getRewardClaimContractForRebasingDT() external view returns (address) {
        return _revenueDistributionModuleStorageV0().rewardClaimForRebasingDT;
    }

    /// @inheritdoc IRevenueDistributionModule
    function getMaxRevSwitchMintCap() external view returns (uint256) {
        return _revenueDistributionModuleStorageV0().maxRevSwitchMintCap;
    }

    /// @inheritdoc IRevenueDistributionModule
    function getMaxAccruingMintCap() external view returns (uint256) {
        return _revenueDistributionModuleStorageV0().maxAccruingMintCap;
    }

    /// @inheritdoc IRevenueDistributionModule
    function getMaxRebasingDTMintCap() external view returns (uint256) {
        return _revenueDistributionModuleStorageV0().maxRebasingDTMintCap;
    }

    /// @inheritdoc IRevenueDistributionModule
    function isRevenueSwitchDistributionPaused() external view returns (bool) {
        return _revenueDistributionModuleStorageV0().revenueSwitchDistributionPaused;
    }

    /// @inheritdoc IRevenueDistributionModule
    function isAccruingDTDistributionPaused() external view returns (bool) {
        return _revenueDistributionModuleStorageV0().accruingDTDistributionPaused;
    }

    /// @inheritdoc IRevenueDistributionModule
    function isRebasingDTDistributionPaused() external view returns (bool) {
        return _revenueDistributionModuleStorageV0().rebasingDTDistributionPaused;
    }
}
"
    },
    "lib/openzeppelin-contracts-upgradeable/contracts/utils/PausableUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)

pragma solidity ^0.8.20;

import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
    /// @custom:storage-location erc7201:openzeppelin.storage.Pausable
    struct PausableStorage {
        bool _paused;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Pausable")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300;

    function _getPausableStorage() private pure returns (PausableStorage storage $) {
        assembly {
            $.slot := PausableStorageLocation
        }
    }

    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    /**
     * @dev The operation failed because the contract is paused.
     */
    error EnforcedPause();

    /**
     * @dev The operation failed because the contract is not paused.
     */
    error ExpectedPause();

    /**
     * @dev Initializes the contract in unpaused state.
     */
    function __Pausable_init() internal onlyInitializing {
        __Pausable_init_unchained();
    }

    function __Pausable_init_unchained() internal onlyInitializing {
        PausableStorage storage $ = _getPausableStorage();
        $._paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        PausableStorage storage $ = _getPausableStorage();
        return $._paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        if (paused()) {
            revert EnforcedPause();
        }
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        if (!paused()) {
            revert ExpectedPause();
        }
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        PausableStorage storage $ = _getPausableStorage();
        $._paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        PausableStorage storage $ = _getPausableStorage();
        $._paused = false;
        emit Unpaused(_msgSender());
    }
}
"
    },
    "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}
"
    },
    "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Muldiv operation overflow.
     */
    error MathOverflowedMulDiv();

    enum Rounding {
        Floor, // Toward negative infinity
        Ceil, // Toward positive infinity
        Trunc, // Toward zero
        Expand // Away from zero
    }

    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds towards infinity instead
     * of rounding towards zero.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        if (b == 0) {
            // Guarantee the same behavior as in a regular Solidity division.
            return a / b;
        }

        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
     * denominator == 0.
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
     * Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0 = x * y; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            if (denominator <= prod1) {
                revert MathOverflowedMulDiv();
            }

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.
            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.

            uint256 twos = denominator & (0 - denominator);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
            // works in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
     * towards zero.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
        }
    }

    /**
     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
     */
    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
        return uint8(rounding) % 2 == 1;
    }
}
"
    },
    "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    /**
     * @dev An operation with an ERC20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data);
        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
    }
}
"
    },
    "src/interfaces/modules/IRevenueDistributionModule.sol": {
      "content": "// SPDX-License-Identifier: Apache-2.0

pragma solidity 0.8.20;

interface IRevenueDistributionModule {
    /*//////////////////////////////////////////////////////////////
                                Events
    //////////////////////////////////////////////////////////////*/

    /// @notice Emitted when revenue switch is distributed
    event RevenueSwitchDistributed(uint256 amount, uint256 timestamp);

    /// @notice Emitted when accruing deposit token is distributed
    event AccruingDTDistributed(uint256 amount, uint256 timestamp);

    /// @notice Emitted when rebasing distribution token is distributed
    event RebasingDTDistributed(uint256 amount, uint256 timestamp);

    /// @notice Emitted when the daily accruing yield rate is updated
    event DailyAccruingYieldRateUpdated(uint256 newDailyAccruingYieldRate);

    /// @notice Emitted when the operator mint cap is updated
    event OperatorMintCapUpdated(uint256 oldMintCap, uint256 newMintCap);

    /// @notice Emitted when the maximum amount of EUR0 that can be minted for revenue switch is updated
    event MaxRevSwitchMintCapUpdated(uint256 newMaxRevSwitchMintCap);

    /// @notice Emitted when the maximum amount of EUR0 that can be minted for accruing deposit token is updated
    event MaxAccruingMintCapUpdated(uint256 newMaxAccruingMintCap);

    /// @notice Emitted when the maximum amount of EUR0 that can be minted for rebasing distribution token is updated
    event MaxRebasingDTMintCapUpdated(uint256 newMaxRebasingDTMintCap);

    /// @notice Emitted when the reward claim contract for revenue switch is updated
    event RewardClaimForRevenueSwitchUpdated(
        address indexed oldRewardClaimContract, address indexed newRewardClaimContract
    );

    /// @notice Emitted when the reward claim contract for accruing deposit token is updated
    event RewardClaimForAccruingDTUpdated(
        address indexed oldRewardClaimContract, address indexed newRewardClaimContract
    );

    /// @notice Emitted when the reward claim contract for rebasing distribution token is updated
    event RewardClaimForRebasingDTUpdated(
        address indexed oldRewardClaimContract, address indexed newRewardClaimContract
    );

    /// @notice Emitted when revenue switch distribution is unpaused
    event RevenueSwitchDistributionUnpaused();

    /// @notice Emitted when revenue switch distribution is paused
    event RevenueSwitchDistributionPaused();

    /// @notice Emitted when accruing deposit token distribution is unpaused
    event AccruingDTDistributionUnpaused();

    /// @notice Emitted when accruing deposit token distribution is paused
    event AccruingDTDistributionPaused();

    /// @notice Emitted when rebasing distribution token distribution is paused
    event RebasingDTDistributionPaused();

    /// @notice Emitted when rebasing distribution token distribution is unpaused
    event RebasingDTDistributionUnpaused();

    /// @notice Distributes the revenue switch to the revenue switch bucket
    /// @param amount The amount to distribute
    /// @dev Can only be called by the OPERATOR_REVSWITCH_DISTRIBUTOR role
    /// @dev The amount should be less than or equal to the mintCap
    /// @dev The revenue switch bucket should be active
    /// @dev This can only be called once a week and when not paused
    function distributeRevenueSwitch(uint256 amount) external;

    /// @notice Distributes the accruing deposit token to the accruing deposit token bucket
    /// @dev The amount to distribute should be calculated by the function
    /// @dev Can only be called by the OPERATOR_ACC_DT_DISTRIBUTOR role
    /// @dev The amount should be less than or equal to the mintCap
    /// @dev This can only be called once a day and when not paused
    function distributeAccruingDT() external;

    /// @notice Distributes the rebasing distribution token to the rebasing distribution token bucket
    /// @param amount The amount to distribute
    /// @dev Can only be called by the OPERATOR_REB_DT_DISTRIBUTOR role
    /// @dev The amount should be less than or equal to the mintCap
    /// @dev This can only be called once a day and when not paused
    function distributeRebasingDT(uint256 amount) external;

    /// @notice Sets the daily accruing yield rate
    /// @param newDailyAccruingYieldRate The new daily accruing yield rate
    /// @dev Can only be called by the OPERATOR_ADMIN_ROLE role
    function setDailyAccruingYieldRate(uint256 newDailyAccruingYieldRate) external;

    /// @notice Sets the mint cap for the overall mint cap
    /// @param newMintCap New mint cap amount
    /// @dev Can only be called by the OPERATOR_ADMIN_ROLE role
    function setOperatorMintCap(uint256 newMintCap) external;

    /// @notice Sets the maximum amount of EUR0 that can be minted for revenue switch
    /// @param newMaxRevSwitchMintCap The new maximum amount of EUR0 that can be minted for revenue switch
    /// @dev Can only be called by the OPERATOR_ADMIN_ROLE role
    function setMaxRevSwitchMintCap(uint256 newMaxRevSwitchMintCap) external;

    /// @notice Sets the maximum amount of EUR0 that can be minted for accruing deposit token
    /// @param newMaxAccruingMintCap The new maximum amount of EUR0 that can be minted for accruing deposit token
    /// @dev Can only be called by the OPERATOR_ADMIN_ROLE role
    function setMaxAccruingMintCap(uint256 newMaxAccruingMintCap) external;

    /// @notice Sets the maximum amount of EUR0 that can be minted for rebasing distribution token
    /// @param newMaxRebasingDTMintCap The new maximum amount of EUR0 that can be minted for rebasing distribution token
    /// @dev Can only be called by the OPERATOR_ADMIN_ROLE role
    function setMaxRebasingDTMintCap(uint256 newMaxRebasingDTMintCap) external;

    /// @notice Sets the reward claim contract address
    /// @param newRewardClaimContract Address of the new reward claim contract for revenue switch
    /// @dev Can only be called by the OPERATOR_ADMIN_ROLE role
    function setRewardClaimForRevenueSwitch(address newRewardClaimContract) external;

    /// @notice Sets the reward claim contract address for accruing deposit token
    /// @param newRewardClaimContract Address of the new reward claim contract for accruing deposit token
    /// @dev Can only be called by the OPERATOR_ADMIN_ROLE role
    /// @dev The reward claim contract should implement ISEur0
    function setRewardClaimForAccruingDT(address newRewardClaimContract) external;

    /// @notice Sets the reward claim contract address for rebasing distribution token
    /// @param newRewardClaimContract Address of the new reward claim contract for rebasing distribution token
    /// @dev Can only be called by the OPERATOR_ADMIN_ROLE role
    function setRewardClaimForRebasingDT(address newRewardClaimContract) external;

    /// @notice Pauses all revenue distribution operations
    /// @dev Can only be called by the PAUSING_CONTRACTS_ROLE role
    function pause() external;

    /// @notice Unpauses all revenue distribution operations
    /// @dev Can only be called by the UNPAUSING_CONTRACTS_ROLE role
    function unpause() external;

    /// @notice Gets the current operator mint cap
    /// @return operatorMintCap The current mint cap
    function getOperatorMintCap() external view returns (uint256);

    /// @notice Gets the daily accruing yield rate
    /// @return dailyAccruingYieldRate The daily accruing yield rate
    function getDailyAccruingYieldRate() external view returns (uint256 dailyAccruingYieldRate);

    /// @notice Gets the reward claim contract address
    /// @return rewardClaimContract The reward claim contract address for revenue switch
    function getRewardClaimContractForRevenueSwitch() external view returns (address);

    /// @notice Gets the reward claim contract address for accruing deposit token
    /// @return rewardClaimContract The reward claim contract address for accruing deposit token
    function getRewardClaimContractForAccruingDT() external view returns (address);

    /// @notice Gets the reward claim contract address for rebasing distribution token
    /// @return rewardClaimContract The reward claim contract address for rebasing distribution token
    function getRewardClaimContractForRebasingDT() external view returns (address);

    /// @notice Gets the maximum amount of EUR0 that can be minted for revenue switch
    /// @return maxRevSwitchMintCap The maximum amount of EUR0 that can be minted for revenue switch
    function getMaxRevSwitchMintCap() external view returns (uint256);

    /// @notice Gets the maximum amount of EUR0 that can be minted for accruing deposit token
    /// @return maxAccruingMintCap The maximum amount of EUR0 that can be minted for accruing deposit token
    function getMaxAccruingMintCap() external view returns (uint256);

    /// @notice Gets the maximum amount of EUR0 that can be minted for rebasing distribution token
    /// @return maxRebasingDTMintCap The maximum amount of EUR0 that can be minted for rebasing distribution token
    function getMaxRebasingDTMintCap() external view returns (uint256);

    /// @notice Pauses revenue switch distribution
    /// @dev Can only be called by the PAUSING_CONTRACTS_ROLE role
    function pauseRevenueSwitchDistribution() external;

    /// @notice Pauses accruing deposit token distribution
    /// @dev Can only be called by the PAUSING_CONTRACTS_ROLE role
    function pauseAccruingDTDistribution() external;

    /// @notice Pauses rebasing distribution token distribution
    /// @dev Can only be called by the PAUSING_CONTRACTS_ROLE role
    function pauseRebasingDTDistribution() external;

    /// @notice Unpauses revenue switch distribution
    /// @dev Can only be called by the UNPAUSING_CONTRACTS_ROLE role
    function unpauseRevenueSwitchDistribution() external;

    /// @notice Unpauses accruing deposit token distribution
    /// @dev Can only be called by the UNPAUSING_CONTRACTS_ROLE role
    function unpauseAccruingDTDistribution() external;

    /// @notice Unpauses rebasing distribution token distribution
    /// @dev Can only be called by the UNPAUSING_CONTRACTS_ROLE role
    function unpauseRebasingDTDistribution() external;

    /// @notice Gets whether revenue switch distribution is paused
    /// @return true if revenue switch distribution is paused, false otherwise
    function isRevenueSwitchDistributionPaused() external view returns (bool);

    /// @notice Gets whether accruing deposit token distribution is paused
    /// @return true if accruing deposit token distribution is paused, false otherwise
    function isAccruingDTDistributionPaused() external view returns (bool);

    /// @notice Gets whether rebasing distribution token distribution is paused
    /// @return true if rebasing distribution token distribution is paused, false otherwise
    function isRebasingDTDistributionPaused() external view returns (bool);
}
"
    },
    "src/interfaces/registry/IRegistryContract.sol": {
      "content": "// SPDX-License-Identifier: Apache-2.0

pragma solidity 0.8.20;

interface IRegistryContract {
    /*//////////////////////////////////////////////////////////////
                                Events
    //////////////////////////////////////////////////////////////*/

    /// @notice This event is emitted when the address of the contract is set
    /// @param name The name of the contract in bytes32
    /// @param contractAddress The address of the contract
    event SetContract(bytes32 indexed name, address indexed contractAddress);

    /*//////////////////////////////////////////////////////////////
                                Functions
    //////////////////////////////////////////////////////////////*/

    /// @notice Set the address of the contract
    /// @param name

Tags:
ERC20, Proxy, Mintable, Burnable, Pausable, Swap, Yield, Upgradeable, Factory, Oracle|addr:0x5b02d233dc5d7a692b701fb78e8bd898f6ae623a|verified:true|block:23690717|tx:0x968777aa94a439089f4bee80adb2417d3ba13936c297e17813e983e9adc10c19|first_check:1761833763

Submitted on: 2025-10-30 15:16:06

Comments

Log in to comment.

No comments yet.