Custom rewards (incentives)

Intro

For the vault owners, Yelay infrastructure provides ways to incentivise depositors with custom on-chain rewards (incentives) and off-chain points.

On-chain incentives can be set up by the vault owners through Yelay UI: https://app.spool.fi/eth/manager/incentives.

Custom off-chain reward points for vaults are set up and managed by the Yelay team - please provide calculation requirements to Yelay during the technical kick-off phase.

To see an example offchain rewards implementation of the SDK in the frontend and try it out yourself, check out the the Yelay v2 SDK Cookbook.

Overview

When a vault is created, the owner or vault admin can set a reward token to incentivize users to deposit into the vault. It is highly recommended that the owner makes an initial deposit before setting any rewards. If there are no deposits, rewards are not accrued to any user, and there is currently no system to retrieve these missed rewards. This feature is still in development.

To add rewards, the owner/admin sends the tokens to the reward manager with specific instructions, including the amount of tokens for the incentive and the end timestamp of the incentive period. Based on these parameters and the current timestamp, a rewardRate per second is calculated (e.g., 1000 tokens for 1 day equals 0.011574074 tokens per second). This reward rate is then divided by the total number of deposit SVTs (total deposits) in the vault. For instance, if there are three users with a combined total of 1400 SVTs, the reward rate per second per SVT would be 0.011574074 / 1400 = 0.000008267.

Users accrue rewards based on their SVT balance multiplied by the per-second reward rate (in our example: SVTbalance * 0,000008267 per second). Whenever a new deposit or withdrawal is made, the total number of SVTs changes, so the reward rate is recalculated accordingly.

Offchain rewards operate similarly, but instead of a blockchain transaction initiating the incentive, it is set directly in our system. The numbers used in actual calculations are much higher than this example, as we compute reward rates in Wei (1ETH = 10^18 Wei) for accuracy.

It's important to note that while the system continually updates the total rewards a user has accrued, it does not account for the rewards the user has already claimed. Therefore, you will need to manage this bookkeeping on your end.

On-chain incentives/rewards

On-chain Custom rewards (incentives) begin accruing on newly deposited funds only after the completion of the 'DoHardWork' function and the subsequent 'Flush' operation following the previous 'DoHardWork' execution.

Users accrue rewards based on their share of the vault.

Accrual of custom rewards (incentives) happens every minute. Users can claim their accumulated weekly rewards every Monday.

There can be max 5 reward tokens per vault.

Configuration

Vault owners can configure arbitrary ERC20 rewards by interacting with the RewardManager smart contract.

Input parameters are:

  • vault address

  • token address

  • timestamp at which rewards stop emitting

  • amount of rewards to emit

Reward tokens are transferred to the smart contract in the same transaction.

Emission rate is computed as the amount of tokens emitted per second.

Vault owners can extend rewards in a similar fashion. If an active configuration with the same reward token exists, the system will take the leftover amount into account when computing the new emission rate. When extending rewards the system requires the new emission rate to be equal or greater than the previous one.

Vault owners and Yelay admin can remove reward configurations.

Retrieval of incentives

To retrieve a list of currently active rewards (incentives) on the Yelay platform, use the following function:

testResult = await yelaySDK.getRewardsInfo(
  {
    networkName,
  }
);

Returns an array of RewardInfo objects:

RewardInfo {
  blockNumber: string;
  rewardrate: string;
  tokenAddress: string;
  vaultAddress: string;
  apy: string;
}

To fetch a list of rewards (incentives) specifically tailored to an individual user on the Yelay platform, use the following method:

testResult = await yelaySDK.getUserRewardInfo(
  {
    userAddress,
    networkName,
  }
);

Returns an array of UserRewardInfo objects:

UserRewardInfo {
  userAddress: string;
  vaultAddress: string;
  tokenAddress: string;
  rewards: BigNumberish;
  lastUpdateTimestamp: BigNumberish;
}

How claiming works

Yelay runs an off-chain RewardManager service, which computes accrued rewards per vault and user at regular intervals. Yelay then snapshots these, builds a Merkle Tree and pushes the Merkle Root on-chain at scheduled intervals (currently once per week).

Users can claim their rewards by interacting with the RewardPool smart contract, passing in their Merkle Proof and leaf information.

Smart contracts:

  • Reward manager (configuration): spool-v2-core/src/rewards/RewardManager.sol at main · SpoolFi/spool-v2-core (github.com)

  • Reward pool (claiming): spool-v2-core/src/rewards/RewardPool.sol at main · SpoolFi/spool-v2-core (github.com)

Claim incentives through SDK

Before attempting to claim incentives, it is necessary to obtain an array of proof objects using the provided function:

testResult = await yelaySDK.getRewardProof(
  {
    userAddress,
    vaultAddress,
    networkName,
  }
);

Returns an array of proof objects used to claim the incentives on the vault:

ClaimRequestStruct = {
  smartVault: string;
  token: string;
  cycle: BigNumberish;
  rewardsTotal: BigNumberish;
  proof: BytesLike[];
};
testResult = await yelaySDK.getUserVaultRewardsInfo(
  {
    userAddress,
    vaultAddress: [vaultAddress] ,
    networkName,
  }
);

Returns an array of user data about incentives on vaults:

UserVaultRewardsData {
  vaultAddress: string;
  vaultName: string;
  rewardTokens: string[];
  vaultRewardsRunningUSD: {
    amounts: string[];
    amountsSum: string;
  };
  vaultRewardsRemainingUSD: {
    amounts: string[];
    amountsSum: string;
  };
  userRewardsClaimable: {
    amounts: string[];
    amountsUSD: string[];
    amountsUSDSum: string;
  };
  userRewardsRunning: {
    amounts: string[];
    amountsUSD: string[];
    amountsUSDSum: string;
  };
  userRewardsTotal: {
    amounts: string[];
    amountsUSD: string[];
    amountsUSDSum: string;
  };
}

Calculate the Annual Percentage Yield (APY) for rewards by leveraging the following function:

testResult = await yelaySDK.getRewardsAPY(
  {
    vaultAddressList: [vaultAddress],
    networkName
  }
);

Returns an array of vault: number Record<string, number>, the numbers being apy values of incentives on vaults

Off-chain incentives/rewards

Configuration

Vault owners can configure arbitrary rewards (also called points) by interacting with the RewardManager API (off-chain).

Users accrue points based on their share of the vault (only deposits after DoHardWork).

Emission rate and point computation algorithm is the same as with the on-chain mechanism - users accrue rewards based on their share of the vault (only deposits after DoHardWork).

Claiming

Yelay runs an off-chain RewardManager service, which computes accrued rewards per vault and user at regular intervals.

Customers can leverage the points mechanism as they see fit - no need to lock funds in the smart contract.

Users typically don’t claim off-chain rewards through Yelay UI or infra

Last updated