# DistributionV5

## Introduction

The `DistributionV5` contract is the core logic and coordination layer of the  protocol on Ethereum. It is responsible for managing all aspects of user staking, calculating reward entitlements, handling multipliers, enforcing locking logic, and coordinating cross-chain reward delivery via LayerZero.

### Key Responsibilities

1. User staking and tracking:
   * Allows users to deposit stETH into the protocol’s staking system.
   * Supports custom staking options like specifying a `claimLockEnd_` (lock duration) and setting a referrer address to benefit from referral multipliers.
   * Keeps detailed records of each user’s stake, including lock periods, multipliers.
2. Reward distribution logic:
   * Computes user reward entitlements based on their stake amount, stake duration, pool configuration, referral status, and global reward emission rates.
   * Allocates rewards across multiple reward pools (“buckets”), such as Capital, Builder, Compute, Code, and Protection — each with independent reward supply and logic.
   * Ensures fair, non-overlapping distribution across these groups.
3. Power factor and referral system:
   * Integrates a lock-based power factor system, rewarding users who lock their claim for longer periods.
   * Implements a referral tier system, where both the referrer and referred user can receive enhanced yield.
   * Dynamically recalculates multipliers on every stake update, using precise mathematical formulas defined in external libraries (e.g., `LinearDistributionIntervalDecrease`, `ReferrerLib`).
4. Cross-chain reward dispatch:
   * After reward calculation, it communicates with the `L1Sender` contract to send reward payloads to Arbitrum (L2).
   * Uses LayerZero to send encoded reward data to the `L2MessageReceiver`, where actual MOR tokens are minted and delivered to users.
5. Data and State Management:
   * Maintains granular, bucket-specific data about user stakes, referral structures, and global reward metrics.
   * Optimizes gas costs and ensures integrity by storing only the necessary state variables and leveraging internal libraries for math and reward logic.

## Storage

### isNotUpgradeable

Returns true if the contract no longer supports upgrades to a new version.

```solidity
bool public isNotUpgradeable;
```

### depositToken

The stETH token address, see the LIDO [doc](https://docs.lido.fi/deployed-contracts/).

```solidity
address public depositToken;
```

### l1Sender

The `L1Sender` contract address.

```solidity
address public l1Sender;
```

### pools

Contain information about MOR reward pools for buckets. `pools[<poolId>]`.

```solidity
Pool[] public pools;
 
struct Pool {
  uint128 payoutStart;
  uint128 decreaseInterval;
  uint128 withdrawLockPeriod;
  uint128 claimLockPeriod;
  uint128 withdrawLockPeriodAfterStake;
  uint256 initialReward;
  uint256 rewardDecrease;
  uint256 minimalStake;
  bool isPublic;
}
```

| Name                           | Description                                                                         |
| ------------------------------ | ----------------------------------------------------------------------------------- |
| `payoutStart`                  | The unix epoch timestamp in seconds when the pool starts to pay out rewards.        |
| `decreaseInterval`             | The interval in seconds between reward decreases.                                   |
| `withdrawLockPeriod`           | The period in seconds when the user can't withdraw his stake.                       |
| `claimLockPeriod`              | The period in seconds when the user can't claim his rewards after the `payoutStart` |
| `withdrawLockPeriodAfterStake` | The period in seconds when the user can't withdraw his stake after staking.         |
| `initialReward`                | The initial MOR reward for the bucket.                                              |
| `rewardDecrease`               | The MOR reward decrease per `decreaseInterval`.                                     |
| `minimalStake`                 | The minimal stake amount                                                            |
| `isPublic`                     | `true` - for Capital bucket, `false` for others.                                    |

### poolsData

Contain additional internal information about MOR reward pools for buckets. `poolsData[<poolId>]`.

```solidity
mapping(uint256 => PoolData) public poolsData;

struct PoolData {
  uint128 lastUpdate;
  uint256 rate;
  uint256 totalVirtualDeposited;
}
```

| Name                    | Description                                                      |
| ----------------------- | ---------------------------------------------------------------- |
| `lastUpdate`            | The unix epoch timestamp when the rate was updated.              |
| `rate`                  | The current pool coefficient, used to calculate awards.          |
| `totalVirtualDeposited` | The total amount of stETH deposited in the pool with multiplier. |

### usersData

Stores all staking-related data for users.  `usersData[<stakerAddress>][<poolId>].`

```solidity
mapping(address => mapping(uint256 => UserData)) public usersData;

struct UserData {
  uint128 lastStake;
  uint256 deposited;
  uint256 rate;
  uint256 pendingRewards;
  uint128 claimLockStart;
  uint128 claimLockEnd;
  uint256 virtualDeposited;
  uint128 lastClaim;
  address referrer;
}
```

| Name             | Description                                                                                                                                           |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| lastStake        | The unix epoch timestamp when the user stake was last.                                                                                                |
| deposited        | The amount of staked stETH.                                                                                                                           |
| rate             | The last user reward rate, used to calculate awards.                                                                                                  |
| pendingRewards   | The last saved MOR rewards for the user. This value is updated when stake, withdraw or claim from the user account occurs. It is not the final award. |
| claimLockStart   | MOR rewards lock period starts at this timestamp.                                                                                                     |
| claimLockEnd     | MOR rewards lock period end at this timestamp.                                                                                                        |
| virtualDeposited | The amount of staked stETH, with multipliers.                                                                                                         |
| lastClaim        | The last claim timestamp.                                                                                                                             |
| referrer         | The referrer address.                                                                                                                                 |

### totalDepositedInPublicPools

Tracks the total amount of stETH deposited in the public pools (specifically the capital bucket).

### poolsLimits

Defines pool-specific limits and parameters. `poolsLimits[<poolId>]` - limits for the capital bucket.

```solidity
mapping(uint256 => PoolLimits) public poolsLimits;

struct PoolLimits {
  uint128 claimLockPeriodAfterStake;
  uint128 claimLockPeriodAfterClaim;
}
```

| Name                        | Description                                                             |
| --------------------------- | ----------------------------------------------------------------------- |
| `claimLockPeriodAfterStake` | The period in seconds when the staker can't claim tokens after staking. |
| `claimLockPeriodAfterClaim` | The period in seconds when the user can't claim tokens after claiming   |

### referrerTiers

Stores referral reward tiers per pool. `referrerTiers[<poolId>][<tierIndex>]`.

```solidity
mapping(uint256 => ReferrerTier[]) public referrerTiers;

struct ReferrerTier {
  uint256 amount;
  uint256 multiplier;
}
```

| Name         | Description                                                      |
| ------------ | ---------------------------------------------------------------- |
| `amount`     | The minimal token amount for the tier                            |
| `multiplier` | The multiplier for the tier, where 1% = 0.01 \* 10<sup>25</sup>. |

### referrersData

Tracks referral activity per user and pool. `referrersData[<stakerAddress>][<poolId>]`.

```solidity
mapping(address => mapping(uint256 => ReferrerData)) public referrersData;

struct ReferrerData {
  uint256 amountStaked;
  uint256 virtualAmountStaked;
  uint256 rate;
  uint256 pendingRewards;
  uint128 lastClaim;
}
```

| Name                | Description                                                              |
| ------------------- | ------------------------------------------------------------------------ |
| amountStaked        | The amount of referred stETH.                                            |
| virtualAmountStaked | The amount of referred stETH, with multipliers.                          |
| rate                | The last referrer reward rate, used to calculate awards.                 |
| pendingRewards      | The last saved MOR rewards for the referrer.  It is not the final award. |
| lastClaim           | The last claim timestamp.                                                |

## Write functions for stakers

### stake

The stake function allows users to deposit stETH into the protocol from the Ethereum network, then the staker will get a share of the rewards.&#x20;

```solidity
stake(
  uint256 poolId_,
  uint256 amount_, 
  uint128 claimLockEnd_, 
  address referrer_
) external;
```

| Name            | Description                                                      |
| --------------- | ---------------------------------------------------------------- |
| `poolId_`       | The reward pool ID.                                              |
| `amount_`       | The stETH amount to stake, where 1 stETH = 10<sup>18.</sup>      |
| `claimLockEnd_` | The unix epoch timestamp in seconds. Use the default zero value. |
| `referrer_`     | The referrer address. Use the default zero address.              |

### withdraw

The withdraw function allows users to retrieve their staked stETH after a withdraw lock period.

```solidity
function withdraw(
  uint256 poolId_, 
  uint256 amount_
) external;
```

| Name      | Description                                                    |
| --------- | -------------------------------------------------------------- |
| `poolId_` | The reward pool ID.                                            |
| `amount_` | The stETH amount to withdraw, where 1 stETH = 10<sup>18.</sup> |

### claim

The claim function enables stakers to receive the MOR tokens they’ve accrued.

```solidity
function claim(
  uint256 poolId_, 
  address receiver_
) external payable;
```

| Name        | Description                             |
| ----------- | --------------------------------------- |
| `poolId_`   | The reward pool ID.                     |
| `receiver_` | The address who will receive MOR on L2. |

### lockClaim

The function to lock rewards and receive claim lock multiplier (power factor). Used when a user has an active stake and wants to receive a multiplier without triggering a new staking transaction.

```solidity
function lockClaim(
  uint256 poolId_,
  uint128 claimLockEnd_
) external poolExists(poolId_);
```

| Name            | Description                          |
| --------------- | ------------------------------------ |
| `poolId_`       | The reward pool ID.                  |
| `claimLockEnd_` | The unix epoch timestamp in seconds. |

### claimReferrerTier

The function enables referrer to receive the MOR tokens they’ve accrued.

```solidity
function claimReferrerTier(
  uint256 poolId_, 
  address receiver_
) external payable poolExists(poolId_);
```

| Name        | Description                             |
| ----------- | --------------------------------------- |
| `poolId_`   | The reward pool ID.                     |
| `receiver_` | The address who will receive MOR on L2. |

## Write functions for contract owner

### Distribution\_init

Initializes the contract. This is a one-time setup function, used during deployment via proxies.

```solidity
function DistributionV5_init(
  address depositToken_,
  address l1Sender_,
  Pool[] calldata poolsInfo_
) external initializer;
```

| Name            | Description                                   |
| --------------- | --------------------------------------------- |
| `depositToken_` | The stETH token address.                      |
| `l1Sender_`     | The `L1Sender` contract address.              |
| `poolsInfo_`    | The rewards pools info (buckets reward info). |

### createPool

The function to create a new reward pool for the bucket.

```solidity
function createPool(Pool calldata pool_) public onlyOwner;
```

| Name    | Description                                 |
| ------- | ------------------------------------------- |
| `pool_` | The rewards pool info (bucket reward info). |

### editPool

The function to edit an existed reward pool for the bucket.

```solidity
function editPool(
  uint256 poolId_,
  Pool calldata pool_
) external onlyOwner poolExists(poolId_);
```

| Name      | Description                                 |
| --------- | ------------------------------------------- |
| `pool_`   | The rewards pool info (bucket reward info). |
| `poolId_` | The reward pool ID.                         |

### editPoolLimits

The function to edit the reward pool limits.

```solidity
function editPoolLimits(
  uint256 poolId_,
  PoolLimits calldata poolLimits_
) external onlyOwner poolExists(poolId_);
```

| Name          | Description            |
| ------------- | ---------------------- |
| `poolId_`     | The reward pool ID.    |
| `poolLimits_` | The pool's limit data. |

### manageUsersInPrivatePool

The function to manage users and their rate in the private pool (not capital bucket). This function specifically controls the user shares in the other buckets.

```solidity
function manageUsersInPrivatePool(
  uint256 poolId_,
  address[] calldata users_,
  uint256[] calldata amounts_,
  uint128[] calldata claimLockEnds_,
  address[] calldata referrers_
) external onlyOwner poolExists(poolId_);
```

| Name             | Description                                   |
| ---------------- | --------------------------------------------- |
| `poolId_`        | The reward pool ID.                           |
| `users_`         | The users addresses.                          |
| `amounts_`       | The virtual staked amount vlaues for `users_` |
| `claimLockEnds_` | The claim lock end values for `users_`.       |
| `referrers_`     | The referrer values for `users_`              |

### editReferrerTiers

The function to setup tiers for the refferal system.

```solidity
function editReferrerTiers(
  uint256 poolId_,
  ReferrerTier[] calldata referrerTiers_
) external onlyOwner poolExists(poolId_)
```

| Name             | Description                 |
| ---------------- | --------------------------- |
| `poolId_`        | The reward pool ID.         |
| `referrerTiers_` | The referrer tiers structs. |

### bridgeOverplus

The function transfers the stETH yield from L1 to L2. Returns the unique identifier for the trabsfer operation from the Arbitrum Bridge.

```solidity
function bridgeOverplus(
  uint256 gasLimit_,
  uint256 maxFeePerGas_,
  uint256 maxSubmissionCost_
) external payable onlyOwner returns (bytes memory);
```

| Name                 | Description                                  |
| -------------------- | -------------------------------------------- |
| `gasLimit_`          | The gas limit for the Arbitrum Bridge.       |
| `maxFeePerGas_`      | The max fee per gas for the Arbitrum Bridge. |
| `maxSubmissionCost_` | The max submission cost.                     |

### removeUpgradeability

The function to remove the possibility to upgrade the smart contract.

```solidity
function removeUpgradeability() external onlyOwner;
```

## Read functions

### getPeriodReward

The function to calculate the bucket rewards for the specified period. Returns the reward amount, where 1 MOR = 10<sup>18</sup>.

```solidity
function getPeriodReward(
  uint256 poolId_,
  uint128 startTime_,
  uint128 endTime_
) external view returns (uint256);
```

| Name         | Description                                                      |
| ------------ | ---------------------------------------------------------------- |
| `poolId_`    | The reward pool ID.                                              |
| `startTime_` | The unix timestamp. Start calculate rewards from this timestamp. |
| `endTime_`   | The unix timestamp. End calculate rewards to this timestamp.     |

### getCurrentUserReward

This function calculates the total claimable MOR token rewards for a given staker within a specific bucket, based on their current stake and multipliers. Where 1 MOR = 10<sup>18</sup>.

```solidity
function getCurrentUserReward(
  uint256 poolId_, 
  address user_
) external view returns (uint256);
```

| Name      | Description         |
| --------- | ------------------- |
| `poolId_` | The reward pool ID. |
| `user_`   | The staker address. |

### getCurrentReferrerReward

This function calculates the total claimable MOR token rewards for a given referrer within a specific bucket, based on referrals and tier multipliers. Where 1 MOR = 10<sup>18</sup>.

```solidity
function getCurrentReferrerReward(
  uint256 poolId_, 
  address user_
) public view returns (uint256)
```

| Name      | Description         |
| --------- | ------------------- |
| `poolId_` | The reward pool ID. |
| `user_`   | The staker address. |

### getClaimLockPeriodMultiplier

The function to calculate the power factor for the specified period. Returns the multiplier, where x1 = 10<sup>25</sup>.

```solidity
function getClaimLockPeriodMultiplier(
  uint256 poolId_,
  uint128 claimLockStart_,
  uint128 claimLockEnd_
) public view returns (uint256)
```

| Name              | Description                                                               |
| ----------------- | ------------------------------------------------------------------------- |
| `poolId_`         | The reward pool ID.                                                       |
| `claimLockStart_` | The unix timestamp. Start calculate the power factor from this timestamp. |
| `claimLockEnd_`   | The unix timestamp. End calculate the power factor to this timestamp.     |

### getCurrentUserMultiplier

The function to calculate the power factor and referrer multiplier for the specified staker. Returns the multiplier, where x1 = 10<sup>25</sup>.

<pre class="language-solidity"><code class="lang-solidity"><strong>function getCurrentUserMultiplier(
</strong>  uint256 poolId_, 
  address user_
) public view returns (uint256)
</code></pre>

| Name      | Description         |
| --------- | ------------------- |
| `poolId_` | The reward pool ID. |
| `user_`   | The staker address. |

### getReferrerMultiplier

The function to calculate the tier multiplier for the specified referrer. Returns the multiplier, where x1 = 10<sup>25</sup>.

```solidity
function getReferrerMultiplier(
  uint256 poolId_,
  address referrer_
) public view returns (uint256)
```

| Name        | Description           |
| ----------- | --------------------- |
| `poolId_`   | The reward pool ID.   |
| `referrer_` | The referrer address. |

### overplus

The function to calculate the current protocol yield, the difference between staked stETH and current contract balance.

```solidity
function overplus() external view returns (uint256);
```


---

# 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://gitbook.mor.org/smart-contracts/documentation/distribution-protocol/v5-protocol/contracts/distributionv5.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.
