Rewards
Technical documentation
Description
Depositing tokens into the concrete's Earn flow provides the user with a ctAsset representing a share of the total amount in the vault. The vault will then move the money to different strategies to generate the best yield possible. Some of the strategies in the vault interact with third-party lending protocols like Aave, Compound, and Radiant. These protocols not only provide yield but also rewards in the form of tokens. For example, Compound provides COMP, and Aave provides AAVE. Holders of the vault shares not only receive yield through the increase in their share values but also are entitled to a portion of the rewards based on the duration they leave their tokens inside the vault.
How does it work?
The vault maintains the state of accrued rewards using an index, which represents the rewards per token at the time of the last claim. This is stored in a mapping as follows:
mapping(address => uint256) public rewardIndex;
The first time a new reward token is collected is added to this array:
address[] private rewardAddresses;
Each concrete vault has a function called harvestRewards
that calls a function with the same name for each strategy. This function returns the reward token and the amount collected. This information is used to calculate the reward index.
Every time a user deposits an amount into the vault, a snapshot of the rewardIndex
is taken for each reward token collected so far:
mapping(address => mapping(address => uint256)) public userRewardIndex;
When the user wants to claim their rewards, they can call claimRewards
on the vault. It will collect all the pending rewards by calculating the difference between the rewardIndex
and the userRewardIndex
for each token. The result of that subtraction is the amount the user will receive per share. Then, the userRewardIndex
is updated with the rewardIndex
value.
What happens in the Strategies?
Each strategy has its own logic to collect rewards based on the specific strategy. The strategy does not account for the rewards claimed. It can only claim rewards and send them to its vault. In cases where the claim is triggered by an action like pulling funds, it will collect the rewards first and send them to the vault once harvestRewards
is executed.
Reference
For a more in-depth rationale of the implementation, please refer to this paper:
Last updated