# RebaseRewardsDistributorV1

### Overview <a href="#overview" id="overview"></a>

**RebaseRewardsDistributorV1** is an upgradeable contract that distributes rebase rewards to **veEYWA** token holders (locks) in the CrossCurve ecosystem. It relies on an **Emission Manager** (`s_emissionManager`) to trigger epoch updates (checkpoints) and fetches locked token data from an **Escrow Manager** (`s_escrowManager`). The contract tracks weekly reward distributions and lets **veEYWA** token holders claim these rebase rewards either directly (if their lock is expired) or by depositing rewards back into the lock (if it’s still active).

Key features include:

1. **Epoch-Based Distribution**: Rewards are recorded in discrete weekly intervals (epochs) and credited to locks according to each lock’s proportional voting power during the relevant weeks.
2. **Checkpointing Logic**: Every time new rebase rewards are added, the contract updates an internal “checkpoint,” distributing the newly added tokens proportionally over the elapsed time since the last checkpoint.
3. **On-Chain Rebase**: Locks continuously earn rebase rewards over time; once claimed, if the lock is still active (not past `unlockTime`), the rewards are automatically re-deposited. Otherwise, they are transferred to the lock owner.
4. **Owner-Only Upgrades**: Using a UUPS proxy pattern, only the contract owner can authorize upgrades to the distributor’s logic.

By implementing `IRebaseRewardsDistributorV1`, **RebaseRewardsDistributorV1** ensures a standardized interface for initialization, checkpoint updates, and reward claims within the CrossCurve ecosystem.

***

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

* **UUPSUpgradeable (OpenZeppelin):**\
  Provides functionality for upgradeable contracts following the UUPS (Universal Upgradeable Proxy Standard) pattern.
* **OwnableUpgradeable (OpenZeppelin):**\
  Gives ownership control, allowing only the owner to authorize upgrades and perform restricted actions.
* **IRebaseRewardsDistributorV1 (Custom Interface):**\
  Declares the core functions (e.g., `initialize`, `checkpoint`, `claim`) and events (`Checkpoint`, `RewardsClaimed`) that define how rebase rewards are managed and distributed.

**Additional External References:**

* **SafeERC20, IERC20 (OpenZeppelin)**: For safe ERC20 transfers of the EYWA token.
* **IEscrowManager**: Provides locked token data (voting power snapshots, `unlockTime`, ownership).
* **IEmissionManagerV1**: Signals new epochs by calling `checkpoint()` and ensures emission periods are up-to-date.

***

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

```solidity
uint256 public constant EPOCH_DURATION = 1 weeks;
```

* **EPOCH\_DURATION**: Specifies that each distribution epoch is exactly one week (604,800 seconds).

***

### State Variables <a href="#state-variables" id="state-variables"></a>

1. **`s_rewardsStartTime (uint256)`**
   * The timestamp (rounded down to the nearest week) at which rewards distribution officially begins.
2. **`s_lastCheckpointTime (uint256)`**
   * Timestamp of the most recent checkpoint, marking when the contract last distributed tokens among the weekly intervals.
3. **`s_previousTokenBalance (uint256)`**
   * The EYWA token balance in the contract before the most recent checkpoint. Used to calculate how many new tokens were added since the last checkpoint.
4. **`s_eywa (IERC20)`**
   * The EYWA token contract used for rebase rewards.
5. **`s_escrowManager (IEscrowManager)`**
   * The escrow manager contract that manages **veEYWA** locks and provides historical voting power data.
6. **`s_emissionManager (IEmissionManagerV1)`**
   * The emission manager contract that calls `checkpoint()` each time new rebase rewards are determined.
7. **`s_weeklyTokensDistributed (uint256[1000000000000000])`**
   * A large array mapping from a week’s starting timestamp (multiple of `EPOCH_DURATION`) to the total tokens distributed in that particular week.
8. **`s_lastClaimedTimeByTokenId (mapping(uint256 => uint256))`**
   * For each **veEYWA** token ID, stores the last epoch’s timestamp at which it fully claimed rebase rewards.

***

### Constructor <a href="#constructor" id="constructor"></a>

```solidity
constructor() {
    _disableInitializers();
}
```

* **Description:**\
  Disables initializers for this upgradeable contract, ensuring `initialize` is called only once in a UUPS proxy context.

***

### External Functions (IRebaseRewardsDistributorV1) <a href="#external-functions-irebaserewardsdistributorv1" id="external-functions-irebaserewardsdistributorv1"></a>

#### 1. **`initialize(...)`** <a href="#id-1-initialize" id="id-1-initialize"></a>

```solidity
function initialize(
    address owner_,
    IERC20 eywa_,
    IEscrowManager escrowManager_,
    IEmissionManagerV1 emissionManager_
) 
    external
    initializer
```

* **Description:**
  * Sets up initial state for the rebase rewards distributor:
    * Assigns contract ownership to `owner_`.
    * Approves the `escrowManager_` to pull unlimited EYWA tokens from this contract.
    * Records the start time of rewards (`s_rewardsStartTime` = current week boundary) and sets initial `s_lastCheckpointTime` similarly.
    * Links the references to `s_eywa`, `s_escrowManager`, and `s_emissionManager`.
* **Parameters:**
  * `owner_`: The address designated as the contract owner.
  * `eywa_`: The EYWA token contract used for distributing rebase rewards.
  * `escrowManager_`: The contract that manages locked positions (NFT-based locks).
  * `emissionManager_`: The contract that triggers checkpoint updates.

***

#### 2. **`checkpoint()`** <a href="#id-2-checkpoint" id="id-2-checkpoint"></a>

```solidity
function checkpoint() external
```

* **Description:**
  * Called only by `s_emissionManager` to record a new checkpoint, distributing newly added tokens across the weeks since the last checkpoint.
  * Reverts if `msg.sender != s_emissionManager` with `UnauthorizedCaller()`.
* **Logic:**
  1. Checks authorization.
  2. Calls `_checkpoint()` to distribute any new tokens proportionally among the weeks that have elapsed since `s_lastCheckpointTime`.

***

#### 3. **`claim(uint256 tokenId_)`** <a href="#id-3-claim-uint256-tokenid" id="id-3-claim-uint256-tokenid"></a>

```solidity
function claim(uint256 tokenId_) external
```

* **Description:**
  * Lets a user claim the rebase rewards for a single **veEYWA** lock identified by `tokenId_`.
  * Requires that `s_emissionManager.s_currentEpochStart()` be updated to or beyond the current week; otherwise reverts with `EmissionPeriodNotUpdated()`.
* **Logic:**
  1. Checks if the emission manager’s `s_currentEpochStart()` is updated to the current epoch.
  2. Calls `_claim(tokenId_, lastCheckpointWeekBoundary)`.
  3. If the lock is expired (`block.timestamp >= unlockTime`), transfers the earned reward to the last lock owner. Otherwise, it deposits the reward back into the lock via `escrowManager_.depositFor(...)`.
  4. Deducts the claimed reward from `s_previousTokenBalance`.

***

#### 4. **`claim(uint256[] calldata tokenIds_)`** <a href="#id-4-claim-uint256-calldata-tokenids" id="id-4-claim-uint256-calldata-tokenids"></a>

```solidity
function claim(uint256[] calldata tokenIds_) external
```

* **Description:**
  * Claims rewards for multiple lock IDs in a single transaction.
  * Similar checks to `claim(uint256)`, verifying the emission period is updated.
  * Iterates over each `tokenId_` in `tokenIds_` and calls the internal `_claim(...)`, summing up the total claimed amount.

***

#### 5. **`earned(uint256 tokenId_)`** <a href="#id-5-earned-uint256-tokenid" id="id-5-earned-uint256-tokenid"></a>

```solidity
function earned(uint256 tokenId_) external view returns (uint256)
```

* **Description:**
  * Returns how many tokens the lock with `tokenId_` has accumulated but not yet claimed, using the latest known checkpoint.
  * Internally calls `_earned(...)` with `s_lastCheckpointTime / EPOCH_DURATION * EPOCH_DURATION` as the last checkpoint boundary.
* **Return:**
  * `uint256`: The unclaimed rebase reward balance for that particular lock ID.

***

### Internal and Private Functions <a href="#internal-and-private-functions" id="internal-and-private-functions"></a>

#### **`_checkpoint()`** <a href="#checkpoint" id="checkpoint"></a>

```solidity
function _checkpoint() private
```

* **Description:**
  * The core logic that distributes newly added EYWA tokens among each weekly interval from the last checkpoint time until `block.timestamp`.
  * If a portion of a week is included, it distributes a proportional share.
* **Logic:**
  1. Calculates `m_totalReward = currentBalanceOfContract - s_previousTokenBalance`.
  2. Spreads this `m_totalReward` proportionally across all full or partial weeks from `s_lastCheckpointTime` to `block.timestamp`.
  3. For each week boundary, updates `s_weeklyTokensDistributed[weekTimestamp] +=` the portion of tokens corresponding to that interval.
  4. Updates `s_previousTokenBalance` to the current contract balance.
  5. Sets `s_lastCheckpointTime = block.timestamp`.
  6. Emits `Checkpoint(block.timestamp, m_totalReward)`.

***

#### **`_claim(...)`** <a href="#claim" id="claim"></a>

```solidity
function _claim(uint256 tokenId_, uint256 lastCheckpointTime_) private returns (uint256)
```

* **Description:**
  * Internal function that calculates how many rebase rewards `tokenId_` has earned since its last claim, updates the last claimed time, and emits `RewardsClaimed`.
  * Returns the amount of newly claimed rewards.
* **Logic:**
  1. Calls `_earned(tokenId_, lastCheckpointTime_)` to compute `(m_reward, m_initialWeekCursor, m_updatedWeekCursor)`.
  2. Sets `s_lastClaimedTimeByTokenId[tokenId_] = m_updatedWeekCursor`.
  3. If `m_reward == 0`, returns immediately. Otherwise emits `RewardsClaimed(tokenId_, m_initialWeekCursor, m_updatedWeekCursor, m_reward)`.
  4. Returns `m_reward` to the caller for final deposit/transfer logic.

***

#### **`_earned(...)`** <a href="#earned" id="earned"></a>

```solidity
function _earned(
    uint256 tokenId_,
    uint256 lastCheckpointTime_
)
    private
    view
    returns (
        uint256 m_reward,
        uint256 m_initialWeekCursor,
        uint256 m_updatedWeekCursor
    )
```

* **Description:**
  * Calculates how many tokens the lock `tokenId_` earned from `m_initialWeekCursor` to `lastCheckpointTime_`, iterating in weekly increments.
  * Uses historical voting power from the `escrowManager.getPastVotesByTokenId(...)` and total supply from `escrowManager.getPastTotalSupply(...)` to determine each week’s share of `s_weeklyTokensDistributed`.
* **Logic:**
  1. Retrieves `m_initialWeekCursor = s_lastClaimedTimeByTokenId[tokenId_]`. If zero, attempts to set it from the lock’s first recorded epoch data in `s_votingPowerPointByTokenIdAndEpoch`.
  2. If `m_initialWeekCursor >= lastCheckpointTime_`, returns zero reward (nothing new to claim).
  3. Iterates at most 52 times (1 year lookback in weekly steps):
     * For each weekly boundary from `m_updatedWeekCursor` to `lastCheckpointTime_`, calculates:
       * `m_balance = escrowManager.getPastVotesByTokenId(tokenId_, nextWeekTimestamp)`
       * `m_supply = escrowManager.getPastTotalSupply(nextWeekTimestamp)` (set to 1 if 0).
       * Distributes `m_reward += (m_balance * s_weeklyTokensDistributed[weekTimestamp]) / m_supply`.
     * Increments `m_updatedWeekCursor` by `EPOCH_DURATION`.
  4. Returns `(m_reward, m_initialWeekCursor, m_updatedWeekCursor)`.

***

### Events <a href="#events" id="events"></a>

1. **`Checkpoint(uint256 indexed timestamp, uint256 indexed totalReward)`**
   * Emitted whenever `_checkpoint()` distributes a new batch of tokens across weekly intervals.
   * `timestamp`: The timestamp of the checkpoint (usually `block.timestamp`).
   * `totalReward`: The number of newly added tokens distributed.
2. **`RewardsClaimed(uint256 indexed tokenId, uint256 indexed initialWeekCursor, uint256 indexed updatedWeekCursor, uint256 reward)`**
   * Emitted whenever a token ID claims rebase rewards.
   * `tokenId`: The veEYWA NFT lock ID that claimed.
   * `initialWeekCursor`: The earliest week boundary for which new rewards are being claimed.
   * `updatedWeekCursor`: The new last claimed week boundary.
   * `reward`: The total tokens claimed in this operation.

***

### Errors <a href="#errors" id="errors"></a>

* **`UnauthorizedCaller()`**
  * Thrown if `checkpoint()` is called by an entity other than `s_emissionManager`.
* **`EmissionPeriodNotUpdated()`**
  * Thrown if a user attempts to claim but the emission manager’s `s_currentEpochStart()` has not been advanced to the current week boundary.

No additional custom errors are introduced beyond those declared in the `IRebaseRewardsDistributorV1` interface.

***

### Summary <a href="#summary" id="summary"></a>

**RebaseRewardsDistributorV1** provides a specialized, upgradeable system for distributing weekly rebase rewards to locks in the CrossCurve ecosystem. It does so by:

* **Recording** new tokens from the emission manager in discrete weekly intervals via `_checkpoint()`.
* **Allowing** token holders to **claim** their proportional share of rebase rewards at any time, either receiving them directly if their lock is expired or re-depositing them if their lock remains active.
* **Integrating** with the escrow manager to read historical voting power for each epoch and proportionally allocate weekly distributed tokens.

By bridging data from the emission manager and the escrow manager, **RebaseRewardsDistributorV1** ensures consistent rebase reward accounting that reflects each lock’s relative stake and time-based accumulation of benefits. It complements the rest of the CrossCurve ecosystem by providing a secure, time-based rebase distribution mechanism with minimal overhead and clear upgrade paths.


---

# 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://docs.crosscurve.fi/developer-documentation/guide-for-developers/technical-documentation-for-crosscurve-dao-smart-contracts/rebaserewardsdistributorv1.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.
