# USD0 Revenue Distribution Module

## High-Level Overview <a href="#high-level-overview" id="high-level-overview"></a>

This contract manages the automated minting and distribution of USD0 tokens to three dedicated distribution buckets. The contract enables multipurpose revenue distribution with three fixed buckets: Revenue Switch, Accruing Deposit Token (Accruing DT), and Rebasing Deposit Token (Rebasing DT). Each bucket operates independently with its own frequency, mint caps, pause mechanisms, and access control.

The core features of this contract include:

**Daily Accruing Deposit Token Distribution**: The contract should be called daily to calculate and mint USD0 tokens into the accruing deposit token vault (SUSD0/UsualS). The amount to mint is automatically calculated based on the vault's total assets and a configurable daily accruing yield rate. After minting, a yield distribution period is started in the vault to distribute the minted tokens over the next 24 hours.

**Daily Rebasing Deposit Token Distribution**: The contract should be called daily to mint a specified amount of USD0 tokens into the rebasing deposit token rewards claim contract. The amount is determined off-chain and provided as a parameter, typically based on an updated Merkle root calculated off-chain.

**Weekly Revenue Switch Distribution**: The contract should be called weekly to receive and mint USD0 rewards from the DAO into the revenue switch rewards claim contract. The amount is determined by the DAO and provided as a parameter when calling the function.

**Mint Cap Management**: The contract maintains a global operator mint cap that restricts the total amount of USD0 that can be minted through Revenue Switch and Rebasing DT distributions. Accruing DT distribution does not consume from the operator mint cap. Each bucket also has its own maximum mint cap per distribution period.

**Granular Pause Mechanisms**: Each distribution bucket can be paused independently, allowing for selective disabling of specific distribution channels without affecting others.

**Access Control**: Each functionality is controlled by a role with minimal required permissions, ensuring secure and restricted access to sensitive operations.

## Contract Summary <a href="#contract-summary" id="contract-summary"></a>

#### Inherited Contracts <a href="#inherited-contracts" id="inherited-contracts"></a>

**PausableUpgradeable**: Allows contract execution to be paused or unpaused by authorized roles. Provides both global pause functionality and per-bucket pause mechanisms.

**IRevenueDistributionModule**: Interface that defines all functions that can be called by anyone (view functions) and role-restricted functions for revenue distribution operations.

#### Storage Structure <a href="#storage-structure" id="storage-structure"></a>

The contract uses ERC-7201 namespaced storage with the following key state variables:

* **operatorMintCap**: Maximum amount of USD0 that can be minted globally (applies to Revenue Switch and Rebasing DT)
* **lastRevenueSwitchDistribution**: Timestamp of last Revenue Switch distribution
* **lastAccruingDTDistribution**: Timestamp of last Accruing DT distribution
* **lastRebasingDTDistribution**: Timestamp of last Rebasing DT distribution
* **dailyAccruingYieldRate**: Daily accruing yield rate in micro basis points (1 = 0.0001%)
* **maxRevSwitchMintCap**: Maximum amount per weekly Revenue Switch distribution
* **maxAccruingMintCap**: Maximum amount per daily Accruing DT distribution
* **maxRebasingDTMintCap**: Maximum amount per daily Rebasing DT distribution
* **rewardClaimForRevenueSwitch**: Address of reward claim contract for Revenue Switch
* **rewardClaimForAccruingDT**: Address of SUSD0 vault for Accruing DT (implements ISUsd0)
* **rewardClaimForRebasingDT**: Address of reward claim contract for Rebasing DT
* **revenueSwitchDistributionPaused**: Boolean flag for Revenue Switch pause state
* **accruingDTDistributionPaused**: Boolean flag for Accruing DT pause state
* **rebasingDTDistributionPaused**: Boolean flag for Rebasing DT pause state

## Functionality Description <a href="#functionality-description" id="functionality-description"></a>

#### Public/External Functions <a href="#publicexternal-functions" id="publicexternal-functions"></a>

**Initialization**

**initialize**: Initializes the contract with the registry address, reward claim contract addresses, and initial parameter values. Sets up all three distribution buckets with their initial timestamps. Can only be called once during contract deployment.

**IRevenueDistributionModule - Distribution Functions**

**distributeRevenueSwitch**:

* Distributes USD0 tokens to the Revenue Switch bucket (weekly)
* Requires `OPERATOR_REVSWITCH_DISTRIBUTOR_ROLE`
* Validates that at least one week has passed since last distribution
* Validates amount against maxRevSwitchMintCap and operatorMintCap
* Reduces operatorMintCap by the distributed amount
* Mints USD0 directly to rewardClaimForRevenueSwitch
* Can only be called when Revenue Switch distribution is not paused

**distributeAccruingDT**:

* Distributes USD0 tokens to the Accruing DT bucket (daily)
* Requires `OPERATOR_ACC_DT_DISTRIBUTOR_ROLE`
* Automatically calculates the amount to distribute based on:
  * `rewardClaimForAccruingDT.totalAssets() * dailyAccruingYieldRate / BASIS_MILLION_POINT_BASE`
* Validates that at least one day has passed since last distribution
* Validates calculated amount against maxAccruingMintCap
* Does not consume from operatorMintCap (unlike other distributions)
* Mints USD0 directly to rewardClaimForAccruingDT vault
* Starts a yield distribution period in the vault using `startYieldDistribution`
* The yield distribution period spans from current timestamp to current timestamp + ONE\_DAY
* Can only be called when Accruing DT distribution is not paused

**distributeRebasingDT**:

* Distributes USD0 tokens to the Rebasing DT bucket (daily)
* Requires `OPERATOR_REB_DT_DISTRIBUTOR_ROLE`
* Takes amount as parameter (typically calculated off-chain from Merkle root)
* Validates that at least one day has passed since last distribution
* Validates amount against maxRebasingDTMintCap and operatorMintCap
* Reduces operatorMintCap by the distributed amount
* Mints USD0 directly to rewardClaimForRebasingDT
* Can only be called when Rebasing DT distribution is not paused

**IRevenueDistributionModule - Configuration Functions (OPERATOR\_ADMIN\_ROLE)**

**setDailyAccruingYieldRate**: Sets the daily accruing yield rate used for calculating Accruing DT distribution amounts. Rate is in micro basis points (1 = 0.0001%), must be between 0 and BASIS\_MILLION\_POINT\_BASE.

**setOperatorMintCap**: Sets the global operator mint cap that limits total USD0 minting through Revenue Switch and Rebasing DT distributions.

**setMaxRevSwitchMintCap**: Sets the maximum amount of USD0 that can be minted per weekly Revenue Switch distribution.

**setMaxAccruingMintCap**: Sets the maximum amount of USD0 that can be minted per daily Accruing DT distribution.

**setMaxRebasingDTMintCap**: Sets the maximum amount of USD0 that can be minted per daily Rebasing DT distribution.

**setRewardClaimForRevenueSwitch**: Updates the reward claim contract address for Revenue Switch.

**setRewardClaimForAccruingDT**: Updates the reward claim contract address for Accruing DT. Must implement ISUsd0 interface.

**setRewardClaimForRebasingDT**: Updates the reward claim contract address for Rebasing DT.

**IRevenueDistributionModule - View Functions**

**getOperatorMintCap**: Returns the current operator mint cap value.

**getDailyAccruingYieldRate**: Returns the current daily accruing yield rate in micro basis points.

**getRewardClaimContractForRevenueSwitch**: Returns the reward claim contract address for Revenue Switch.

**getRewardClaimContractForAccruingDT**: Returns the reward claim contract address for Accruing DT.

**getRewardClaimContractForRebasingDT**: Returns the reward claim contract address for Rebasing DT.

**getMaxRevSwitchMintCap**: Returns the maximum amount of USD0 that can be minted per weekly Revenue Switch distribution.

**getMaxAccruingMintCap**: Returns the maximum amount of USD0 that can be minted per daily Accruing DT distribution.

**getMaxRebasingDTMintCap**: Returns the maximum amount of USD0 that can be minted per daily Rebasing DT distribution.

**isRevenueSwitchDistributionPaused**: Returns whether Revenue Switch distribution is currently paused.

**isAccruingDTDistributionPaused**: Returns whether Accruing DT distribution is currently paused.

**isRebasingDTDistributionPaused**: Returns whether Rebasing DT distribution is currently paused.

**IRevenueDistributionModule - Pause Functions**

**pause**: Pauses all contract operations. Can only be called by `PAUSING_CONTRACTS_ROLE`.

**unpause**: Unpauses all contract operations. Can only be called by `UNPAUSING_CONTRACTS_ROLE`.

**pauseRevenueSwitchDistribution**: Pauses only Revenue Switch distribution. Can only be called by `PAUSING_CONTRACTS_ROLE`.

**unpauseRevenueSwitchDistribution**: Unpauses Revenue Switch distribution. Can only be called by `UNPAUSING_CONTRACTS_ROLE`.

**pauseAccruingDTDistribution**: Pauses only Accruing DT distribution. Can only be called by `PAUSING_CONTRACTS_ROLE`.

**unpauseAccruingDTDistribution**: Unpauses Accruing DT distribution. Can only be called by `UNPAUSING_CONTRACTS_ROLE`.

**pauseRebasingDTDistribution**: Pauses only Rebasing DT distribution. Can only be called by `PAUSING_CONTRACTS_ROLE`.

**unpauseRebasingDTDistribution**: Unpauses Rebasing DT distribution. Can only be called by `UNPAUSING_CONTRACTS_ROLE`.

## Functionality Breakdown <a href="#functionality-breakdown" id="functionality-breakdown"></a>

#### Setting up Calculation Parameters <a href="#setting-up-calculation-parameters" id="setting-up-calculation-parameters"></a>

`OPERATOR_ADMIN_ROLE` can change all parameter values used in distribution calculations:

* Daily accruing yield rate (used in Accruing DT amount calculation)
* Operator mint cap (global limit for Revenue Switch and Rebasing DT)
* Individual bucket maximum mint caps

There is no timelock for these changes, allowing for rapid response to market conditions or protocol needs.

#### Daily Accruing Deposit Token Distribution <a href="#daily-accruing-deposit-token-distribution" id="daily-accruing-deposit-token-distribution"></a>

`OPERATOR_ACC_DT_DISTRIBUTOR_ROLE` is required to call `distributeAccruingDT` every 24 hours to:

1. Query the total assets value from the accruing deposit token vault (SUSD0)
2. Calculate the distribution amount: `totalAssets * dailyAccruingYieldRate / BASIS_MILLION_POINT_BASE`
3. Validate the calculated amount against maxAccruingMintCap
4. Mint the calculated amount of USD0 directly to the SUSD0 vault
5. Start a yield distribution period in the vault that distributes the minted tokens over the next 24 hours

**Note**: This distribution does not consume from the operator mint cap, as it is calculated based on vault assets rather than being an arbitrary amount set by an operator.

The amount distributed scales based on the vault's total assets, ensuring that as more users deposit into the vault, more yield is distributed proportionally.

#### Daily Rebasing Deposit Token Distribution <a href="#daily-rebasing-deposit-token-distribution" id="daily-rebasing-deposit-token-distribution"></a>

`OPERATOR_REB_DT_DISTRIBUTOR_ROLE` is required to call `distributeRebasingDT` with a valid amount every 24 hours. The amount is typically calculated off-chain based on an updated Merkle root:

1. Off-chain calculation determines the total USD0 amount to mint for eligible users
2. The amount is provided as a parameter to `distributeRebasingDT`
3. The contract validates the amount against maxRebasingDTMintCap and operatorMintCap
4. If valid, the operatorMintCap is reduced by the amount
5. USD0 is minted directly to the rebasing deposit token rewards claim contract
6. Users can claim their portion using valid Merkle proofs

This distribution requires off-chain infrastructure (Watchtower) to calculate the Merkle root and determine the total distribution amount based on eligible users and their assigned allocations.

#### Weekly Revenue Switch Distribution <a href="#weekly-revenue-switch-distribution" id="weekly-revenue-switch-distribution"></a>

`OPERATOR_REVSWITCH_DISTRIBUTOR_ROLE` is required to call `distributeRevenueSwitch` with a valid amount every week. The amount is determined by the DAO:

1. DAO determines the weekly USD0 rewards amount to distribute
2. The amount is provided as a parameter to `distributeRevenueSwitch`
3. The contract validates that at least one week has passed since last distribution
4. The contract validates the amount against maxRevSwitchMintCap and operatorMintCap
5. If valid, the operatorMintCap is reduced by the amount
6. USD0 is minted directly to the revenue switch rewards claim contract

This distribution enables the DAO to directly allocate USD0 rewards on a weekly basis, separate from the automated daily distributions.

#### Mint Cap Management <a href="#mint-cap-management" id="mint-cap-management"></a>

The contract implements a two-tier mint cap system:

1. **Operator Mint Cap**: Global limit for USD0 minting through Revenue Switch and Rebasing DT distributions. This cap is consumed when either of these distributions occurs and can be increased by `OPERATOR_ADMIN_ROLE` if needed.
2. **Per-Bucket Maximum Mint Caps**: Each distribution bucket has its own maximum amount that can be minted per distribution period:
   * `maxRevSwitchMintCap`: Maximum per weekly Revenue Switch distribution
   * `maxAccruingMintCap`: Maximum per daily Accruing DT distribution
   * `maxRebasingDTMintCap`: Maximum per daily Rebasing DT distribution

Both the operator mint cap and per-bucket caps must be satisfied for a distribution to proceed (except Accruing DT, which only checks its own cap).

#### Granular Pause Mechanisms <a href="#granular-pause-mechanisms" id="granular-pause-mechanisms"></a>

The contract supports both global and per-bucket pause functionality:

* **Global Pause**: Pauses all contract operations. Can be used in emergencies to halt all distributions.
* **Per-Bucket Pause**: Each distribution bucket can be paused independently:
  * `pauseRevenueSwitchDistribution` / `unpauseRevenueSwitchDistribution`
  * `pauseAccruingDTDistribution` / `unpauseAccruingDTDistribution`
  * `pauseRebasingDTDistribution` / `unpauseRebasingDTDistribution`

This granular control allows administrators to disable specific distribution channels without affecting others, useful for addressing issues in a single bucket or temporarily suspending specific revenue streams.

#### Accruing DT Yield Distribution Period <a href="#accruing-dt-yield-distribution-period" id="accruing-dt-yield-distribution-period"></a>

When `distributeAccruingDT` is called, after minting USD0 to the SUSD0 vault, the contract calls `startYieldDistribution` on the vault with:

* `yieldAmount`: The minted USD0 amount
* `startTime`: Current block timestamp
* `endTime`: Current block timestamp + ONE\_DAY

This initiates a yield distribution period in the vault where the minted tokens are distributed over the next 24 hours to vault holders proportionally. The vault's yield-bearing mechanism ensures that shares appreciate in value as yield accrues throughout the day.

#### Rebasing DT Merkle Root Integration <a href="#rebasing-dt-merkle-root-integration" id="rebasing-dt-merkle-root-integration"></a>

The Rebasing DT distribution relies on off-chain infrastructure (Watchtower) to:

1. Calculate eligible users and their allocations
2. Generate a Merkle root from these allocations
3. Determine the total USD0 amount to mint
4. Provide the amount to `distributeRebasingDT`

The actual user claims happen through the rewards claim contract using Merkle proofs, not directly through the Revenue Distribution Module.

## Constants <a href="#constants" id="constants"></a>

**OPERATOR\_REVSWITCH\_DISTRIBUTOR\_ROLE**: Role required to distribute USD0 to Revenue Switch bucket (weekly)

**OPERATOR\_ACC\_DT\_DISTRIBUTOR\_ROLE**: Role required to distribute USD0 to Accruing DT bucket (daily)

**OPERATOR\_REB\_DT\_DISTRIBUTOR\_ROLE**: Role required to distribute USD0 to Rebasing DT bucket (daily)

**OPERATOR\_ADMIN\_ROLE**: Role required to set configuration parameters (mint caps, yield rates, reward claim addresses)

**PAUSING\_CONTRACTS\_ROLE**: Role required to pause the contract or individual distribution buckets

**UNPAUSING\_CONTRACTS\_ROLE**: Role required to unpause the contract or individual distribution buckets

**CONTRACT\_REGISTRY\_ACCESS**: Constant used to define the address of the registry access contract

**CONTRACT\_USD0**: Constant used to define the address of the USD0 contract

**INITIAL\_REVENUE\_DISTRIBUTION\_MINT\_CAP**: Initial value for operator mint cap (50,000 USD0)

**ONE\_DAY**: Duration of one day in seconds (86,400 seconds)

**ONE\_WEEK**: Duration of one week in seconds (604,800 seconds)

**BASIS\_MILLION\_POINT\_BASE**: Base value for calculating percentages in micro basis points (1,000,000, where 1 = 0.0001%)

### Safeguard Implementation <a href="#safeguard-implementation" id="safeguard-implementation"></a>

#### Access Control <a href="#access-control" id="access-control"></a>

The contract uses `CheckAccessControl` to enforce role-based access control, ensuring only authorized addresses can perform actions that require specific permissions. Each role has minimal required permissions:

* Distribution roles can only trigger their specific distribution type
* Admin role can only modify configuration parameters
* Pausing roles can only pause/unpause functionality

#### Pausability <a href="#pausability" id="pausability"></a>

The contract is pausable at both global and per-bucket levels:

* Global pause can halt all operations in emergencies
* Per-bucket pause allows selective disabling of specific distribution channels
* Separate pausing and unpausing roles prevent unauthorized changes

#### Mint Cap Restrictions <a href="#mint-cap-restrictions" id="mint-cap-restrictions"></a>

Multiple layers of mint cap validation prevent excessive minting:

1. Operator mint cap limits total USD0 minting (for Revenue Switch and Rebasing DT)
2. Per-bucket maximum caps limit individual distribution amounts
3. Both caps must be satisfied for distributions to proceed

#### Time-Based Restrictions <a href="#time-based-restrictions" id="time-based-restrictions"></a>

Distribution functions enforce time-based restrictions to prevent abuse:

* Accruing DT can only be distributed once per day
* Rebasing DT can only be distributed once per day
* Revenue Switch can only be distributed once per week

These restrictions prevent operators from rapidly minting excessive amounts and ensure distributions occur at appropriate intervals.

#### Input Validation <a href="#input-validation" id="input-validation"></a>

All functions validate inputs:

* Non-zero addresses for reward claim contracts
* Non-zero amounts where applicable
* Yield rate bounds (0 to BASIS\_MILLION\_POINT\_BASE)
* Same value checks to prevent redundant updates

#### Invariant Validation <a href="#invariant-validation" id="invariant-validation"></a>

The contract maintains system invariants:

* Operator mint cap cannot be exceeded (except for Accruing DT which doesn't consume it)
* Distribution amounts must respect per-bucket maximum caps
* Time restrictions ensure distributions occur at proper intervals
* Pause states prevent distributions when buckets are disabled

**Note**: In scenarios where overcollateralization invariants are at risk, the contract can be paused or individual buckets can be disabled as a feature flag to protect the system.

#### Restrictions on Function Call Frequency <a href="#restrictions-on-function-call-frequency" id="restrictions-on-function-call-frequency"></a>

There are strict time-based limits for distribution functions:

* `distributeAccruingDT`: Can only be called once per 24 hours
* `distributeRebasingDT`: Can only be called once per 24 hours
* `distributeRevenueSwitch`: Can only be called once per week (7 days)

These restrictions prevent unwanted emissions and ensure distributions occur at controlled, predictable intervals. The time checks use block timestamps and enforce minimum periods between distributions.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tech.usual.money/smart-contracts/protocol-contracts/usd0/usd0-revenue-distribution-module.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
