MOR distribution. Step #2

The DepositPool contract is responsible for the internal allocation of MOR tokens among participants who have staked tokens in the pool. While the total amount of MOR rewards is calculated and assigned per pool by the external Distributor contract, the DepositPool determines how those rewards are split among individual users.

Staking and virtual stake

When a user deposits tokens, they are immediately forwarded to the Distributor contract for yield generation. However, within DepositPool, the user’s deposit, applied multipliers (such as power factor bonuses or referral boosts), and resulting virtual stake are recorded. The virtual stake is calculated by multiplying the user’s actual deposit by their multipliers, thus capturing not just the amount staked but also the user’s commitment and contribution to the protocol.

Daily MOR allocation and cumulative reward coefficient

Unlike yield sources like Aave that accrue rewards continuously, stETH generates yield via a rebasing mechanism once per day. As a result, MOR distribution from the Distributor to each DepositPool also happens daily. This timing constraint ensures alignment with stETH’s yield schedule.

Internally, each DepositPool uses a cumulative reward coefficient to represent how many MOR tokens have been distributed per unit of virtual stake. When new MOR tokens are allocated to the pool, the coefficient is increased accordingly, reflecting the new available rewards.

Reward Calculation Formula

User rewards are calculated lazily — that is, only when a user interacts with the contract (e.g., stake, withdraw, or claim), rather than updating every user on each reward deposit. The calculation is performed using the following logic:

uint256 userReward = pendingRewards + virtualStake * (poolRewardCoefficient - userRewardCoefficient);
  • pendingRewards - rewards that were calculated after the stake or withdrawal of depositToken — that is, after the user’s share was modified.

  • virtualStake - the user’s current stake after applying multipliers.

  • poolRewardCoefficient - the current accumulated MOR per unit of virtual stake across the entire pool.

  • userRewardCoefficient - the coefficient stored at the time of the user’s last interaction.

The poolRewardCoefficient is updated globally when new rewards are distributed. It is calculated as:

uint256 poolRewardCoefficient += distributedRewards / totalVirtualStake;
  • distributedRewards - is the amount of MOR tokens allocated to the pool during distribution.

  • totalVirtualStake - is the sum of all users’ virtual stake (after applying lock/referral multipliers) at the time of distribution.

This model allows each user’s reward to be efficiently and fairly computed based on the delta in the coefficient since their last update.

Claiming and Unstaking

When a user claims MOR tokens or unstakes from the pool, the contract first updates their reward using the above formula. Then, it issues the corresponding MOR amount and updates the user’s stored coefficient to the latest global value. This ensures that each user receives exactly their fair share of the distributed tokens.

Design Advantages

By utilizing a cumulative coefficient and lazy updates, the DepositPool can support a large number of users without incurring high gas costs on reward distribution. While it doesn’t determine the total amount of MOR emitted, it guarantees an efficient and accurate internal distribution that reflects both user behavior and their contribution to the system.

Last updated

Was this helpful?