Delegation Pool Rewards Explainer

This page gives a detailed explanation about rewards for delegation pools.

Overview

The rewards transferred to a delegation pool are distributed based on a time-weighted delegation amount. Within the same pool, if more delegators join, the rewards (temporally fixed, as they are transferred every 24 hours at 0:00 UTC) will be shared among all participants, potentially reducing the rewards for an individual in the short term. However, as the pool grows with larger delegation amounts, the daily rewards transferred to the pool can also increase. This leads to a gradual rise in the total claimable rewards for all participants.

For instance, when a new participant delegates a significant amount, the proportional share of rewards for existing participants might initially decrease due to the adjustment in the total time-weighted delegation amount. This happens because the claimable function calculates the rewards for each participant based on their time-weighted contribution relative to the overall pool size. However, as the system stabilizes and the increased delegation amount results in higher daily rewards, all participants, including the new and existing ones, benefit from the larger pool of rewards over time.

This mechanism ensures a dynamic balance between fairness and incentive for long-term delegation. Existing participants are rewarded for their earlier contributions through accumulated time-weight factors, while new participants contribute to the growth of the reward pool. As the delegation pool matures, the fluctuations in individual rewards diminish, creating a more stable and predictable distribution. This equilibrium encourages sustained engagement and supports the long-term sustainability of the reward system.

For more details, please check our code at https://basescan.org/address/0x1a15d5bf8cdb6b1241903806e844fb72ebd48af6#code

Calculation

On Day 1, at 00:01 UTC, Address A delegates aa FLOCK to a pool. Over the course of nn days, with daily rewards of r1r_1 FLOCK transferred to the pool, the total claimable rewards in the pool are n×r1n×r_1 FLOCK. By the end of Day nn, Address A can claim the rewards:

R1=n×r1R_1=n\times r_1

On Day n+1n+1, at 00:01 UTC, another participant, Address B, delegates bb FLOCK into the same pool. At 12:00 UTC on Day n+1n+1, the rewards for Day n+1n+1have not been transferred to the pool (because the new daily reward will be transferred at 00:00 UTC on Day n+2n+2), but the claimable rewards for Address A remain based on the previous time-weighted contributions. At this point:

  • Total claimable rewards in the pool remain n×r1n \times r_1 FLOCK.

  • Because B joined only 12 hours ago, based on our time‐weight logic, B’s stake has “0.5 days” of weighting, while A’s stake has n+0.5n+0.5 days accumulated. Thus, address A's claimable rewards are updated as:

R2=n×r1×(n+0.5)×a(n+0.5)×a+b×0.5 R_2=n\times r_1 \times \frac{(n + 0.5) \times a}{(n + 0.5) \times a+ b \times 0.5}

However, as the delegation amount in the pool increases, the rewards transferred for Day n+1n+1 also increase. For example, if r2r_2 FLOCK are transferred to the pool as rewards for Day n+1n+1, then:

  • The total claimable rewards in the pool become: n×r1+r2n \times r_1 + r_2 FLOCK

  • Address A’s claimable rewards are recalculated as:

R3=(n×r1+r2)×(n+1)×a(n+1)×a+b×1R_3=(n\times r_1 +r_2) \times \frac{(n + 1) \times a}{(n + 1) \times a+ b \times 1}

Assume that other network conditions do not change, and the rewards transferred to the pool are proportional to the total delegation amount, i.e., r2r1=a+ba\frac{r_2}{r_1} = \frac{a+b}{a}. Therefore:

R3=(n+a+ba)×r1×(n+1)×a(n+1)×a+b×1R_3=(n +\frac{a+b}{a}) \times r_1 \times \frac{(n + 1) \times a}{(n + 1) \times a+ b \times 1}

Thus, the ratio between R3R_3 and R3R_3 is:

R3R1=1n×(n+a+ba)×(n+1)×a(n+1)×a+b×1=1n×(n+1)×a+ba×(n+1)×a(n+1)×a+b=n+1n\frac{R_3}{R1} = \frac{1}{n} \times (n +\frac{a+b}{a}) \times \frac{(n + 1) \times a}{(n + 1) \times a+ b \times 1} = \frac{1}{n} \times \frac{(n+ 1) \times a+b}{a} \times \frac{(n + 1) \times a}{(n + 1) \times a+ b} = \frac{n+1}{n}

This means that the overall rewards for the address A are increasing over time .

Examples

For n=2,a=100,b=1000,r1=10,r2=110n=2, a= 100, b= 1000, r_1 = 10, r_2 = 110:

  • R1R_1: Address A’s rewards on Day nn before Address B joins: 20 FLOCK.

  • R2R_2: Address A’s rewards on Day n+1n+1 after Address B joins but before new rewards are transferred: 6.67 FLOCK.

  • R3R_3: Address A’s rewards on Day n+1n+1 after new rewards are transferred to the pool: 27.69 FLOCK.

And for n=30,a=1000,b=1000,r1=10,r2=20n=30, a= 1000, b= 1000, r_1 = 10, r_2 = 20:

  • R1R_1: Address A’s rewards on Day nn before Address B joins: 300 FLOCK.

  • R2R_2: Address A’s rewards on Day n+1n+1 after Address B joins but before new rewards are transferred: 295.1612903 FLOCK.

  • R3R_3: Address A’s rewards on Day n+1n+1 after new rewards are transferred to the pool: 310 FLOCK.

Here are more examples with various settings:

r0
10
10
10
10
10

r1

110

110

20

20

12

a

100

100

1000

1000

5000

b

1000

1000

1000

1000

1000

n

2

30

30

60

60

R1

20

300

300

600

600

R2

6.67

257.75

295.16

595.08

599.01

R3

30

310

310

610

610

R2/R1

33.33%

85.92%

98.39%

99.18%

99.83%

R3/R1

150.00%

103.33%

103.33%

101.67%

101.67%

Code & Remarks

/**
 * @notice Get the total claimable rewards for a delegator
 * @param _delegator The delegator address
 */
function claimable(address _delegator) public view returns (uint256) {
    uint256 rewards = config.getFlockToken().balanceOf(address(this)).sub(totalDelegationAmount);
    uint256 receiverTemporalDelegationAmount = receiverTemporalDelegation(_delegator);
    uint256 totalTemporalDelegationAmount = totalTemporalDelegation();
    if (totalTemporalDelegationAmount == 0) {
        return 0;
    }
    return receiverTemporalDelegationAmount.mul(rewards).div(totalTemporalDelegationAmount);
}

Such significant changes in claimable rewards typically occur when $n$ is small, and the newly joined delegation amount is relatively large compared to the existing delegation amounts in the pool. This is because, during these early stages, the time-weighted delegation factor (represented by receiverTemporalDelegationAmount and totalTemporalDelegationAmount in the claimable function) is more sensitive to changes introduced by new participants.

From the function logic:

  1. The total rewards available for distribution (rewards) are derived from the balance of the FLOCK token in the pool, excluding the total delegation amount (totalDelegationAmount).

  2. The claimable rewards for a specific delegator are proportional to their receiverTemporalDelegationAmount, which reflects their time-weighted contribution to the pool.

  3. Any large addition to the pool's delegation amount significantly alters the totalTemporalDelegationAmount, impacting the proportional share of claimable rewards for all participants.

However, as the delegation pool operates over an extended period, and more participants join, the pool's totalTemporalDelegationAmount stabilizes due to accumulated time weights across all participants. At this point, the relative impact of any single new delegation becomes negligible. Consequently, fluctuations in claimable rewards diminish, and the system approaches a steady state where the rewards distribution is more predictable and less volatile.

Free-Rider Delegation? Impossible!

One might wonder if Address B, in our example, could exploit the system by performing malicious activities to gain rewards without making a meaningful contribution—essentially attempting free-rider delegation. Such actions might involve the following steps:

  1. Address B delegates to the pool and immediately gains a share of the unclaimed rewards already in the pool.

  2. Address B quickly claims the rewards from the shared pool.

  3. Address B then undelegates from the pool before the rewards for Day n+1 are transferred, thereby avoiding the need to actually contribute to the delegation amount when rewards are distributed in the FLock Task Manager contract.

This sequence might appear to allow Address B to game the system by gaining rewards without a genuine long-term commitment to the pool.

Why is Free-Riding not Possible?

This kind of exploit is effectively prevented by a critical safeguard in our system: delegators are required to maintain their delegation for at least 24 hours before they are eligible to undelegate their stake.

This mechanism ensures that all participants in the pool contribute meaningfully to the delegation amount for a sufficient period before benefiting from the shared rewards. By enforcing this time constraint, the system maintains fairness and eliminates opportunities for free-rider delegation.

See the code:

/**
 * @notice Undelegate tokens
 * @param _amount The amount of tokens to undelegate
 */
function undelegate(uint256 _amount) external {
    address delegator = msg.sender;
    require(lastStakeTimestamp[delegator] + 1 days < block.timestamp, "You can't undelegate before 1 day");
    require(delegationOf(delegator).amount >= _amount, "User has insufficient token delegated");
    require(config.getFlockToken().transfer(delegator, _amount), "transfer failed");
    addPastTemporalDelegation(delegator, delegationMap[delegator]);
    delegationMap[delegator] = DelegationInfo(delegationMap[delegator].amount.sub(_amount), block.timestamp);
    updateTotalDelegationInfoAndPastTemporalDelegation(0, _amount, 0, 0);
    totalDelegationAmount -= _amount;
    if (delegationOf(delegator).amount == 0) {
        delegators.remove(delegator);
    }
    config.getMainManager().afterDelegationUpdate(user);
    emit Undelegate(delegator, user, _amount);
}

See here for deep-dive into our smart contracts for AI Arena.

Last updated