Reward Pool Drip Models

The drip model for a reward pool defines the rate at which assets deposited into the reward pool accrue (i.e. "drip") to stakers.

Drip models must conform to the IDripModel interface, and may use a reward pool's last drip time to determine the returned drip factor.

interface IDripModel {
  /// @notice Returns the drip factor, the percentage of undripped rewards which should drip to stakers, as a wad. For
  /// example, it there are 100 undripped reward assets and this method returns 1e17, then 100 * 1e17 / 1e18 = 10 assets
  /// will drip.
  /// @param lastDripTime_ Timestamp of the last drip
  function dripFactor(uint256 lastDripTime_) external view returns (uint256 dripFactor_);

The drip model gets specified in the RewardPoolConfig struct when a config is passed during Rewards Manager deployment or update (see Define Rewards Manager Configuration). Note the drip model can differ for each individual reward pool.

For details on how exactly rewards drip works, check here.

Exponential-rate drip model

A default exponential-rate drip model implemented in DripModelExponential.

The drip rate is a fixed number, uint256 public immutable ratePerSecond. In this model, rewards drip according to the exponential decay function A = U * (1 - r)^t, where:

  • U is the starting amount of undripped rewards

  • A is the remaining amount of undripped rewards after some number of seconds

  • t is the number of elapsed seconds

  • r is the per-second drip rate

From some simple math, we can compute the r value for a desired rate of drip.

Suppose you want to drip 25% of rewards per year. You then make the following substitutions:

  • U is 1, or 100%, since we don't care what the actual starting value is, only what it decays to.

  • A is 0.75 because the desired drip rate is 25%, and 100% reduced by 25% is 75%.

  • t is 31557600, the number of seconds in a year. The time period is arbitrary. We use a year only because our target rate is 25% drip per year.

This results in the following formula:

0.75 = 1 * (1 - r ) ^ 31557600

We may now solve for r as follows:

0.75 = 1 * (1 - r ) ^ 31557600 0.75 = (1 - r ) ^ 31557600 0.75 ^ (1 / 31557600) = 1 - r 0.75 ^ (1 / 31557600) - 1 = - r r = -((0.75 ^ (1 / 31557600)) - 1) r = 0.000000009...

Finally, we can multiply r by a wad to get ratePerSecond is approximately 9e9.

Deploying a exponential-rate drip model

If you would like to deploy the exponential-rate drip model and use it for reward pools in the Rewards Manager, you can use the dedicated DripModelExponentialFactory.

To deploy the model, call the following function on that factory:

/// @notice Deploys a DripModelExponential contract and emits a DeployedDripModelExponential event that
/// indicates what the params from the deployment are. This address is then cached inside the
/// isDeployed mapping.
/// @return model_ which has an address that is deterministic with the input ratePerSecond_.
function deployModel(uint256 ratePerSecond_) external returns (DripModelExponential model_);

Because the deployModel function is deterministic, it will revert if a model with your desired configurations already exists. To first confirm that your model needs to be deployed, you can call the getModel function with the same params you would pass to deployModel. The getModel function will return the address of the model that has your desired configs, if one exists.

The most up-to-date instructions on how to use the factory can be found in its source code.

For the addresses of factories deployed to various chains, see our contracts deployments registry.

Last updated