EscrowVoteManagerV1

Overview

EscrowVoteManagerV1 is a smart contract that manages voting power distribution and reward allocation for gauge contracts associated with various pools in the EYWA ecosystem. It integrates with the escrow manager, gauge and rewards distributor factories, and the emission manager to facilitate:

  • Voting with Locked Tokens: Users holding escrowed (locked) EYWA tokens can vote on pools to direct emissions (rewards) toward specific gauges.

  • Gauge Creation and Management: Authorized entities (e.g., owner/DAO) can create, kill, and revive gauges for different pools, enabling dynamic reward allocation.

  • Rewards Distribution: The contract accumulates reward amounts from the emission manager and distributes them proportionally to gauges based on the votes cast in previous epochs.

  • Token Whitelisting: Maintains a whitelist of tokens eligible for reward distributions.

By leveraging epoch-based logic and integrating closely with the emission manager and escrow manager, EscrowVoteManagerV1 ensures a fair and flexible governance mechanism that aligns incentives between token holders and liquidity pools.


Inherited Contracts and Interfaces

  • UUPSUpgradeable: Manages upgrade logic for UUPS (Universal Upgradeable Proxy Standard) deployments.

  • OwnableUpgradeable: Provides ownership access control, allowing only the contract owner to perform certain critical operations.

  • IEscrowVoteManagerV1: Defines the interface for managing gauge votes, reward notifications, and incentive claims.

Additional External References:

  • SafeERC20, IERC20: Used for safe interactions with ERC20 tokens.

  • Math: Utility library for math operations.

  • IEscrowManager: Provides access to escrowed token balances, voting checks, and owner references.

  • IRewardsDistributorFactoryV1: Factory contract for creating rewards distributors associated with gauges.

  • IGaugeFactoryV1: Factory contract for creating gauge contracts for pools.

  • IGaugeV1: Interface for gauge contracts that handle reward distribution to liquidity providers.

  • IEmissionManagerV1: Manages weekly emissions and provides current epoch information.

  • IRewardsDistributor: Distributes incentives and handles depositing/withdrawing user votes.

  • IDistributionCreator: Provides campaign parameters for gauge creation and reward distribution campaigns.


Constants

EPOCH_DURATION

  • Type: uint256

  • Value: 1 weeks

  • Description: Duration of each epoch in seconds. Aligns voting and reward distribution schedules.

PRECISION

  • Type: uint256

  • Value: 1e18

  • Description: Precision factor used for calculations to maintain integer arithmetic accuracy.


State Variables

Core Addresses and Interfaces

  • s_emissionManager

    • Type: address

    • Description: Address of the emission manager contract that controls weekly EYWA emissions.

  • s_eywa

    • Type: address

    • Description: The address of the EYWA token contract.

  • s_escrowManager

    • Type: IEscrowManager

    • Description: Interface to the escrow manager contract, which handles locked tokens and provides voting power data.

  • s_rewardsDistributorFactory

    • Type: IRewardsDistributorFactoryV1

    • Description: Factory for creating incentive rewards distributors for new gauges.

  • s_gaugeFactory

    • Type: IGaugeFactoryV1

    • Description: Factory for creating new gauge contracts associated with pools.

Voting and Distribution

  • _s_distributionIndex

    • Type: uint256

    • Description: Global distribution index used to calculate claimable rewards for each gauge, updated when new rewards are notified.

  • s_pools

    • Type: address[]

    • Description: Array of registered pool addresses. Each pool can have an associated gauge.

  • s_gaugeByPool

    • Type: mapping (address => address)

    • Description: Maps a pool address to its corresponding gauge address.

  • s_poolByGauge

    • Type: mapping (address => address)

    • Description: Reverse mapping from a gauge address to its associated pool.

  • s_incentiveRewardsDistributorByGauge

    • Type: mapping (address => address)

    • Description: Maps a gauge to its incentive rewards distributor address, where votes are deposited and rewards claimed.

  • s_votesByEpochAndPool

    • Type: mapping (uint256 => mapping (address => uint256))

    • Description: Tracks total votes allocated to each pool per epoch start timestamp.

  • s_claimableRewardsByGauge

    • Type: mapping (address => uint256)

    • Description: Accumulated claimable EYWA rewards for each gauge. Distributed when _distributeRewards is called.

  • s_lastDistributionTimestampByGauge

    • Type: mapping (address => uint256)

    • Description: Tracks the last distribution timestamp for each gauge to ensure rewards are distributed after an epoch update.

  • s_isGauge

    • Type: mapping (address => bool)

    • Description: Indicates if a given address is recognized as a gauge.

  • s_isWhitelistedToken

    • Type: mapping (address => bool)

    • Description: Indicates if a token is whitelisted for incentive distribution.

  • s_isActiveGauge

    • Type: mapping (address => bool)

    • Description: Indicates if a gauge is currently active and eligible for rewards.

Token Voting

  • s_usedVotesByTokenId

    • Type: mapping (uint256 => uint256)

    • Description: The number of votes currently used (allocated) by a particular escrowed token ID.

  • s_lastVotedTimestampByTokenId

    • Type: mapping (uint256 => uint256)

    • Description: Timestamp of the last vote cast by each token ID, used to determine if votes can be reset or updated.

  • s_votedPoolsByTokenId

    • Type: mapping (uint256 => address[])

    • Description: The list of pools a given token ID has voted for in the current epoch.

  • s_totalVotesByEpoch

    • Type: mapping (uint256 => uint256)

    • Description: Total votes cast across all pools in a given epoch.

  • s_votesByTokenIdAndPool

    • Type: mapping (uint256 => mapping (address => uint256))

    • Description: Number of votes allocated by a specific token ID to a particular pool.

Distribution Indexing

  • _s_supplyDistributionIndex

    • Type: mapping (address => uint256)

    • Description: The distribution index per gauge. Used in reward calculation to determine how much of the globally notified rewards a gauge can claim.


Constructor

  • constructor()

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


External Functions

initialize(...)

Signature:

function initialize(
    address owner_,
    address emissionManager_,
    address eywa_,
    IEscrowManager escrowManager_,
    IRewardsDistributorFactoryV1 rewardsDistributorFactory_,
    IGaugeFactoryV1 gaugeFactory_,
    address[] calldata whitelistedTokens_
) external initializer

Description: Initializes the contract state, sets the owner, references to external contracts, and whitelists initial tokens.

Parameters:

  • owner_: Address of the contract owner.

  • emissionManager_: Address of the emission manager contract.

  • eywa_: Address of the EYWA token contract.

  • escrowManager_: Reference to the escrow manager contract.

  • rewardsDistributorFactory_: Reference to the rewards distributor factory.

  • gaugeFactory_: Reference to the gauge factory.

  • whitelistedTokens_: Array of token addresses to whitelist initially.

Effects:

  • Sets core addresses and interfaces.

  • Marks given tokens as whitelisted.

  • Transfers contract ownership to owner_.


createGauge(...)

Signature:

function createGauge(address pool_, IDistributionCreator.CampaignParameters calldata campaignParameters_) external onlyOwner

Description: Creates a new gauge for a specified pool. Also creates an associated incentive rewards distributor. Only callable by the owner.

Parameters:

  • pool_: Address of the pool for which the gauge is created.

  • campaignParameters_: Parameters defining the reward distribution campaign.

Constraints & Checks:

  • The gauge must not already exist for the given pool.

Effects:

  • Deploys a new gauge via the gauge factory.

  • Deploys a new incentive rewards distributor.

  • Maps the new gauge and distributor to the pool.

  • Marks the gauge as active and emits GaugeCreated.


killGauge(...)

Signature:

function killGauge(address gauge_) external onlyOwner

Description: Deactivates a gauge, preventing it from receiving future rewards. Unclaimed rewards are returned to the emission manager’s treasury.

Parameters:

  • gauge_: Address of the gauge to deactivate.

Constraints & Checks:

  • The gauge must be active.

Effects:

  • Transfers any claimable rewards back to the emission manager’s treasury.

  • Marks the gauge as inactive.

  • Emits GaugeKilled.


reviveGauge(...)

Signature:

function reviveGauge(address gauge_) external onlyOwner

Description: Reactivates a previously killed gauge, allowing it to receive rewards again.

Parameters:

  • gauge_: Address of the gauge to reactivate.

Constraints & Checks:

  • The gauge must not already be active.

Effects:

  • Marks the gauge as active.

  • Emits GaugeRevived.


setWhitelistStatusForTokens(...)

Signature:

function setWhitelistStatusForTokens(address[] calldata tokens_, bool[] calldata statuses_) external onlyOwner

Description: Updates the whitelist status for a batch of tokens. Only callable by the owner.

Parameters:

  • tokens_: Array of token addresses to update.

  • statuses_: Matching array of boolean values, true to whitelist, false to remove.

Constraints & Checks:

  • Length of tokens_ must match statuses_.

Effects:

  • Updates the whitelist status of each token.

  • Emits WhitelistStatusUpdatedForTokens.


vote(...)

Signature:

function vote(
    uint256 tokenId_,
    address[] calldata pools_,
    uint256[] calldata weights_
) external

Description: Casts votes for specified pools using the given escrowed token ID’s voting power. The voting power is sourced from IEscrowManager. The caller must be authorized to operate tokenId_.

Parameters:

  • tokenId_: ID of the escrowed token used to vote.

  • pools_: Array of pool addresses to vote for.

  • weights_: Relative weights allocated to each pool.

Checks:

  • Arrays pools_ and weights_ must be non-empty and of equal length.

  • Caller must be authorized for tokenId_.

Effects:

  • Calls _vote internally to allocate votes.

  • Updates the last voted timestamp for tokenId_.


reset(...)

Signature:

function reset(uint256 tokenId_) external

Description: Resets votes for a given token ID, withdrawing allocated votes from all pools. The caller must be authorized for tokenId_.

Parameters:

  • tokenId_: ID of the token whose votes are reset.

Effects:

  • Calls _reset internally to remove existing votes.

  • Updates the last voted timestamp for tokenId_.


poke(...)

Signature:

function poke(uint256 tokenId_) external

Description: Recalculates and updates votes for the specified token ID based on its current voting power. Useful if the token’s voting power changed. The caller must be authorized for tokenId_.

Parameters:

  • tokenId_: ID of the token to recalculate votes for.

Effects:

  • Retrieves previously voted pools and weights.

  • Calls _vote again to update allocations according to new voting power.

  • Updates the last voted timestamp for tokenId_.


claimIncentives(...)

Signature:

function claimIncentives(
    address[] calldata incentiveRewardsDistributors_, 
    address[][] calldata rewardTokens_
) external

Description: Allows the caller to claim incentive rewards from multiple distributors. Each distributor may offer multiple tokens as rewards.

Parameters:

  • incentiveRewardsDistributors_: Array of distributor addresses.

  • rewardTokens_: Parallel array of reward tokens per distributor.

Effects:

  • For each distributor, calls getReward to transfer earned tokens to the caller.


notifyRewardAmount(...)

Signature:

function notifyRewardAmount(uint256 rewardAmount_) external

Description: Notifies the contract of a new EYWA reward amount to distribute. Only callable by the emission manager.

Parameters:

  • rewardAmount_: Amount of EYWA tokens to be distributed as rewards.

Effects:

  • Calculates the per-vote weight increase (_s_distributionIndex update).

  • Emits RewardNotified.


distributeRewardsForMultipleGauges(...)

Signature:

function distributeRewardsForMultipleGauges(address[] calldata gauges_) external

Description: Distributes accumulated rewards to an array of specified gauges. Updates the epoch before distribution.

Parameters:

  • gauges_: Array of gauge addresses to distribute rewards to.

Effects:

  • Calls _distributeRewards for each gauge.


distributeRewardsForGaugesInRange(...)

Signature:

function distributeRewardsForGaugesInRange(uint256 start_, uint256 end_) external

Description: Distributes accumulated rewards to gauges in a specified range of the s_pools array. Updates the epoch before distribution.

Parameters:

  • start_: Starting index in s_pools.

  • end_: Ending index in s_pools.

Effects:

  • Iterates over the specified range of pools.

  • Calls _distributeRewards for each gauge.


getPoolsCount()

Signature:

function getPoolsCount() external view returns (uint256)

Description: Returns the total number of registered pools.

Return:

  • uint256: The number of pools.


nextEpochStart()

Signature:

function nextEpochStart() external view returns (uint256)

Description: Returns the timestamp of the next epoch start.

Return:

  • uint256: Timestamp for the next epoch’s start.


currentEpochStart()

Signature:

function currentEpochStart() external view returns (uint256)

Description: Returns the timestamp of the current epoch start.

Return:

  • uint256: Timestamp for the current epoch’s start.


Internal Functions

_vote(...)

Signature:

function _vote(
    uint256 tokenId_,
    uint256 votingPower_,
    address[] memory pools_,
    uint256[] memory weights_
) private

Description: Allocates voting power to specified pools, updating epoch-based vote counts and depositing votes into incentive rewards distributors.

Logic:

  1. _reset(tokenId_) to remove old votes.

  2. Compute total weight sum and allocate votes proportionally to each pool.

  3. Update s_votesByEpochAndPool and s_votesByTokenIdAndPool.

  4. Deposit votes into the incentive rewards distributor.

  5. Update s_totalVotesByEpoch and set s_usedVotesByTokenId.


_reset(...)

Signature:

function _reset(uint256 tokenId_) private

Description: Removes existing votes for a token ID, withdrawing votes from incentive distributors and updating epoch totals.

Logic:

  1. Retrieve previously voted pools.

  2. For each pool, remove allocated votes from s_votesByEpochAndPool and s_votesByTokenIdAndPool.

  3. Withdraw votes from incentive rewards distributors, if applicable.

  4. Update s_totalVotesByEpoch and s_usedVotesByTokenId.


_distributeRewards(...)

Signature:

function _distributeRewards(address gauge_, uint256 currentEpochStart_) private

Description: Distributes accumulated claimable rewards to a specific gauge if the current epoch has advanced and the gauge is active.

Logic:

  1. Ensure gauge is active and current epoch is beyond last distribution time.

  2. Update reward indexes with _updateRewardIndexForGauge.

  3. Transfer claimable rewards to the gauge and call notifyRewardAmount on the gauge.

  4. Reset s_claimableRewardsByGauge[gauge_] and record distribution event.


_updateRewardIndexForGauge(...)

Signature:

function _updateRewardIndexForGauge(address gauge_, uint256 currentEpochStart_) private

Description: Updates the reward index for a gauge based on previous epoch’s votes and the global _s_distributionIndex.

Logic:

  1. Retrieve last epoch’s votes for the gauge’s pool.

  2. Calculate the delta in the global distribution index since last update.

  3. Increase s_claimableRewardsByGauge[gauge_] by the proportionate amount.

  4. Store the new distribution index state for the gauge.


Events

  • GaugeCreated: Emitted when a new gauge is created.

  • GaugeKilled: Emitted when a gauge is deactivated.

  • GaugeRevived: Emitted when a gauge is reactivated.

  • WhitelistStatusUpdatedForTokens: Emitted when token whitelist statuses are updated.

  • RewardNotified: Emitted when a new reward amount is notified.

  • VoteCast: Emitted when a token ID casts votes for a pool.

  • VotesAbstained: Emitted when votes are reset (abstained) for a token ID.

  • RewardsDistributed: Emitted when rewards are distributed to a gauge.


Errors

  • GaugeDoesNotExist(): Thrown if no gauge exists for the provided pool.

  • GaugeAlreadyExists(): Thrown if trying to create a gauge for a pool that already has one.

  • GaugeNotActive(): Thrown if attempting to interact with an inactive gauge.

  • GaugeAlreadyActive(): Thrown if attempting to revive a gauge that is already active.

  • UnauthorizedAccess(): Thrown if caller is not authorized for the requested action.

  • InvalidArrayLengths(): Thrown if input arrays differ in length when they should match.

  • ZeroEntry(): Thrown if a zero allocation occurs where a nonzero value is expected.

  • AlreadyVoted(): Thrown if a token ID attempts to vote again without resetting.


Summary

EscrowVoteManagerV1 provides a robust and upgradeable system for directing EYWA token emissions to liquidity pools through gauges. By enabling authorized changes to gauges, handling epochs and voting power distributions, and offering flexible reward claims, it aligns user incentives with protocol growth. Its modular integration with escrow managers, gauge factories, and reward distributors ensures a scalable and fair distribution of rewards based on community-driven voting power.

Last updated