Protocol yield generation
Overview
This document describes how the protocol generates yield from user deposits, how that yield is handled based on strategy type, and under what conditions it is sent to the L1SenderV2 contract for cross-chain reward minting.
Yield generation overview
When users stake tokens into deposit pools, those tokens may be used in different yield strategies, depending on the pool configuration. The protocol currently supports the following strategies:
AAVE- token is deposited into Aave to generate yield.NO_YIELD- token is not used in any external protocol. This is typically used forstETH.NONE- no yield logic is applied (only for private buckets without real stake).
Strategy-Specific Deposit Behavior
When a user calls supply()
For AAVE Strategy:
The user transfers the underlying
tokento theDistributor.The
Distributorsupplies the token to the Aave protocol viaAaveIPool.supply().Yield is later measured by checking the
aTokenbalance of theDistributor.
For NO_YIELD Strategy (e.g., stETH):
stETH):The user transfers
stETHto theDistributor.It is not deposited anywhere; yield is not actively generated.
Instead, the
stETHis held and passively earns staking rewards (as per Lido).
Reward Distribution Timing and Constraints
Rewards are distributed using distributeRewards() which performs the following:
Fetch emitted MOR - calls
RewardPool.getPeriodRewards()using the last distribution timestamp.Check if distribution is due: public pools must respect
minRewardsDistributePeriod(e.g., once per day).This is enforced because
stETHyield is not readable on-chain per second or block. It's accrued slowly, and daily intervals allow consistent accounting.
Update Prices:
For each deposit pool in the reward pool, the price of the deposit token is fetched from Chainlink (via
ChainLinkDataConsumer).This allows yield across tokens (USDC, WETH, etc.) to be normalized to a dollar value.
Calculate Yield Per Pool. See MOR distribution. Step #1
Calculate Pool Shares. See MOR distribution. Step #1
Update State. See MOR distribution. Step #1
Transferring Yield to L1SenderV2
The protocol does not retain accrued yield within the Distributor contract. Instead, yield is extracted and forwarded to L1SenderV2 selectively — only for the specific DepositPool that triggers the operation.
At the end of a yield cycle (e.g., daily), when any function (e.g., supply, withdraw, or withdrawYield) is called on a given deposit pool, the Distributor contract:
Calls
distributeRewardsto calculate and assign MOR rewards based on relative yield of all deposit pools in the same reward pool.Then calls
_withdrawYieldonly for theDepositPoolinvolved in the transaction, transferring its actual yield toL1SenderV2.
Yield is transferred using the following logic:
For
AAVE:Calls
AaveIPool.withdraw()to redeemaTokens.Transfers the withdrawn tokens to
L1SenderV2.
For
NO_YIELD:Transfers the excess tokens directly (if any) to
l1SeL1SenderV2nder.
Once the tokens are with L1SenderV2, they can be:
Bridged to Arbitrum.
Used for minting MOR rewards for users via
sendMintMessage().
Notes
stETHpools useNO_YIELDbecause stETH natively accrues rewards via rebasing.The yield on
stETHcannot be measured at each block — hence daily distribution is preferred.Price-based yield normalization ensures fair distribution even when token values vary.
Last updated
Was this helpful?