RebaseRewardsDistributorV1

Overview

RebaseRewardsDistributorV1 is a contract designed to distribute β€œrebase” rewards to veEYWA token holders over time. It integrates with the escrow manager, which handles locked veEYWA tokens, and the emission manager, which determines the emission epochs. The contract aims to:

  • Distribute EYWA token rewards proportionally to the voting power (veEYWA balance) of each token over weekly epochs.

  • Update and record reward distributions at checkpoints to ensure accurate and time-aligned allocations.

  • Allow token holders to claim their accumulated rewards at any time.

  • Automatically deposit claimed rewards into the corresponding lock if it is still active, or transfer them directly to the owner if the lock is expired.

Key Features:

  • Epoch-Based Distribution: Rewards are distributed on a weekly basis (1 week per epoch).

  • Checkpoints: The contract records reward distributions at checkpoints. Each checkpoint corresponds to changes in reward balances over time.

  • Claiming Rewards: Holders of veEYWA tokens can claim their accrued rewards. If the associated lock is active, claimed rewards are added to that lock. Otherwise, rewards are transferred directly to the lock owner.

  • Integration with Ecosystem Contracts: The contract relies on IEscrowManager for lock status and voting power data, and on IEmissionManagerV1 for ensuring up-to-date emission periods before claims.


Inherited Contracts and Interfaces

  • UUPSUpgradeable (OpenZeppelin): Provides upgradeability using the UUPS proxy standard.

  • OwnableUpgradeable (OpenZeppelin): Enables ownership functionalities, restricting certain operations (like upgrades) to the owner.

  • IRebaseRewardsDistributorV1: Defines the interface for initialization, checkpointing, claiming rewards, and calculating earned amounts.

Additional External References:

  • SafeERC20, IERC20 (OpenZeppelin): For safely handling ERC20 token transfers.

  • Math (OpenZeppelin): Provides mathematical utilities.

  • IEscrowManager: Provides data about veEYWA locks, including unlock times, voting power history, and token ownership.

  • IEmissionManagerV1: Ensures that the emission period is updated before rewards can be claimed.


Constants

EPOCH_DURATION

  • Type: uint256

  • Value: 1 weeks

  • Description: Duration of each emission and reward distribution epoch, aligning all calculations to weekly intervals.


State Variables

  • s_rewardsStartTime

    • Type: uint256

    • Description: The timestamp at which reward distribution starts. Aligned to an epoch boundary.

  • s_lastCheckpointTime

    • Type: uint256

    • Description: The timestamp of the last recorded checkpoint. Used for distributing rewards proportionally over elapsed time.

  • s_previousTokenBalance

    • Type: uint256

    • Description: The EYWA token balance of this contract at the last checkpoint, used to calculate newly added rewards since the last checkpoint.

  • s_eywa

    • Type: IERC20

    • Description: The EYWA token contract used for distributing rebase rewards.

  • s_escrowManager

    • Type: IEscrowManager

    • Description: Reference to the escrow manager that manages veEYWA locks and provides data on voting power, ownership, and lock status.

  • s_emissionManager

    • Type: IEmissionManagerV1

    • Description: Reference to the emission manager contract which controls weekly emissions. It must update emission periods before claims are processed.

  • s_weeklyTokensDistributed

    • Type: uint256[1000000000000000]

    • Description: Large static array mapping from a weekly timestamp (epoch start) to the amount of tokens distributed that week. This allows calculating how many tokens were allocated in each epoch.

  • s_lastClaimedTimeByTokenId

    • Type: mapping(uint256 => uint256)

    • Description: Tracks the last claimed timestamp for each veEYWA token ID. Used to calculate how many weeks of rewards remain unclaimed.


Constructor

  • constructor()

    • Description: Disables initializers to prevent re-initialization of this upgradeable contract.


External Functions

initialize(...)

Signature:

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

Description: Initializes the contract state. Sets the owner, references to EYWA token, escrow manager, and emission manager. Aligns s_rewardsStartTime and s_lastCheckpointTime to epoch boundaries and approves the escrow manager to transfer unlimited EYWA tokens on behalf of this contract.

Parameters:

  • owner_: Address of the contract owner.

  • eywa_: The EYWA token contract.

  • escrowManager_: The escrow manager contract reference.

  • emissionManager_: The emission manager contract reference.

Effects:

  • Calls __UUPSUpgradeable_init() and __Ownable_init(owner_).

  • Sets s_rewardsStartTime and s_lastCheckpointTime to the nearest epoch boundary (current time truncated to multiple of EPOCH_DURATION).

  • Approves the escrow manager for EYWA token transfers.


checkpoint()

Signature:

function checkpoint() external

Description: Records a new checkpoint to distribute rewards proportional to the time elapsed since the last checkpoint. Only callable by the emission manager contract. This function calculates how many new tokens were added since the last checkpoint and allocates them to the appropriate weeks in s_weeklyTokensDistributed.

Checks:

  • msg.sender must be address(s_emissionManager), otherwise UnauthorizedCaller() is thrown.

Effects:

  • Updates s_weeklyTokensDistributed for each relevant week, proportionally distributing newly added tokens over the elapsed time.

  • Updates s_previousTokenBalance and s_lastCheckpointTime.

  • Emits Checkpoint event.


claim(uint256 tokenId_)

Signature:

function claim(uint256 tokenId_) external

Description: Claims all accrued rewards for a specific veEYWA token ID. Before claiming, checks that the emission period is updated. The earned rewards are determined by calculating the token’s voting power over each unclaimed epoch and the total tokens distributed. If the lock is active, rewards are deposited into that lock via the escrow manager. If the lock is expired, tokens are transferred directly to the lock’s last owner.

Parameters:

  • tokenId_: The veEYWA token ID for which to claim rewards.

Checks:

  • s_emissionManager.s_currentEpochStart() must not be less than the current epoch (determined by block.timestamp / EPOCH_DURATION * EPOCH_DURATION), otherwise EmissionPeriodNotUpdated() is thrown.

Effects:

  • Calls the internal _claim function to calculate and distribute rewards.

  • Updates s_previousTokenBalance by subtracting the claimed amount.

  • Emits RewardsClaimed event if rewards are claimed.


claim(uint256[] calldata tokenIds_)

Signature:

function claim(uint256[] calldata tokenIds_) external

Description: Claims rewards for multiple veEYWA token IDs in a single transaction. The same checks, logic, and effects as claim(uint256 tokenId_) are applied to each token ID in the array.

Parameters:

  • tokenIds_: Array of token IDs for which to claim rewards.

Checks:

  • Same emission period check as single claim.

Effects:

  • Iterates through each tokenId_, calling _claim internally.

  • Aggregates the total claimed rewards and subtracts from s_previousTokenBalance.

  • Emits a RewardsClaimed event for each token ID that has rewards.


earned(uint256 tokenId_)

Signature:

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

Description: View function to calculate how many rewards a given tokenId_ would earn if claimed at the current moment, without actually claiming them.

Parameters:

  • tokenId_: The veEYWA token ID to check.

Return:

  • uint256: The amount of unclaimed rewards earned by tokenId_.

Logic:

  • Calls the internal _earned function to compute the reward based on weekly distributions and voting power history.


Internal Functions

_checkpoint()

Signature:

function _checkpoint() private

Description: Called by checkpoint() to handle the logic of distributing newly observed tokens since the last checkpoint over the elapsed time. Divides the distribution proportionally among weeks that passed.

Logic:

  1. Compute m_totalReward = balanceOf(this) - s_previousTokenBalance.

  2. Spread m_totalReward across each relevant epoch interval proportionally to the elapsed time.

  3. Update s_weeklyTokensDistributed accordingly.

Effects:

  • Updates s_previousTokenBalance and s_lastCheckpointTime.

  • Emits Checkpoint.


_claim(uint256 tokenId_, uint256 lastCheckpointTime_)

Signature:

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

Description: Handles the logic of claiming rewards for a single token ID. It calls _earned to compute how many tokens the ID is owed, updates s_lastClaimedTimeByTokenId, and returns the reward amount.

Parameters:

  • tokenId_: The veEYWA token ID to claim for.

  • lastCheckpointTime_: The truncated last checkpoint time.

Return:

  • uint256: The amount of claimed rewards.

Effects:

  • Updates s_lastClaimedTimeByTokenId[tokenId_].

  • Emits RewardsClaimed if m_reward > 0.


_earned(uint256 tokenId_, uint256 lastCheckpointTime_)

Signature:

function _earned(
    uint256 tokenId_,
    uint256 lastCheckpointTime_
) private view returns (uint256, uint256, uint256)

Description: Calculates how many rewards a token ID earned between s_lastClaimedTimeByTokenId[tokenId_] and lastCheckpointTime_. It iterates up to 52 epochs backward, retrieving voting power and total supply data from s_escrowManager, and sums the proportional share of s_weeklyTokensDistributed for each epoch.

Parameters:

  • tokenId_: The veEYWA token ID to calculate earnings for.

  • lastCheckpointTime_: Reference time for calculation (truncated to epoch boundary).

Return:

  • (uint256 m_reward, uint256 m_initialWeekCursor, uint256 m_updatedWeekCursor):

    • m_reward: total calculated rewards.

    • m_initialWeekCursor: starting epoch for the calculation.

    • m_updatedWeekCursor: ending epoch after calculation.

Logic:

  • Determines the initial claiming week from s_lastClaimedTimeByTokenId[tokenId_].

  • For each week until lastCheckpointTime_ or up to 52 weeks, calculates the ratio of the token’s past voting power to the total supply and multiplies by that week’s distributed tokens.

  • Accumulates m_reward accordingly.


Events

Checkpoint

Emitted When: A new checkpoint is recorded distributing tokens over elapsed time since the last checkpoint.

Parameters:

  • timestamp: The time at which the checkpoint was made.

  • totalReward: The total new reward observed since the last checkpoint.

RewardsClaimed

Emitted When: A token ID claims its accrued rewards.

Parameters:

  • tokenId: The veEYWA token ID claiming rewards.

  • initialWeekCursor: The starting epoch of reward accumulation.

  • updatedWeekCursor: The ending epoch after calculating earned rewards.

  • reward: Amount of reward claimed.


Errors

  • UnauthorizedCaller(): Thrown if a restricted function like checkpoint() is called by an unauthorized entity.

  • EmissionPeriodNotUpdated(): Thrown if claim() is attempted before the emission manager has updated the emission period for the current epoch.


Summary

RebaseRewardsDistributorV1 manages weekly reward distributions for veEYWA token holders. By creating checkpoints, tracking newly added tokens, and storing how many tokens were distributed each week, it allows for fair and accurate calculation of accrued rewards. The contract ensures that claims only occur after emission periods are up-to-date and properly accounts for active versus expired locks when distributing claimed rewards. This structure fosters a stable and incentive-aligned environment for participants in the EYWA ecosystem.

Last updated