GM Incentives
Token rewards for GM Lending and Looping activity
This contract manages and distributes token incentives as a way to reward certain GM Lending Pool activity. The contract inherits from OpenZeppelin's Pausable, Ownable, and ReentrancyGuard contracts.
constructor
At deployment, the constructor sets the deployer (msg.sender
) as the owner (referred to hereafter as Admin). It also stores the USDC vault, the rewards vault, and the Lending Pool in state variables.
Admin Functions
pause
Pauses functions with the whenNotPaused
modifier. Only the Admin can call.
unpause
Unpauses functions with the whenNotPaused
modifier. Only the Admin can call.
setVaults
Updates the USDC vault and reward wallet if needed. This can only be called by the Admin.
Parameters:
_usdcVault
address
The address for the USDC vault
_rewardsVault
address
The address for the rewards token wallet
configureReward
Configures reward tokens for Lending Pool incentives, using the RewardsConfigInput:
Using the config inputs, this function ensures there are enough tokens in the rewards vault for the entirety of the desired distribution. If the reward is a new incentive, then the reward is mapped to true in the _isRewardEnabled
mapping, and the reward address is stored in the _rewardsList
array.
_updateRewardData()
is then called. If it's the first time configuring the reward asset, emissions are skipped, and the internal call only updates lastUpdateTimestamp
. If reconfiguring a reward, the reward index is updated before changes are made to the emissions.
The reward's emissionsPerSecond
, distributionEnd
, and totalSupply
are stored/updated. Upon success, the call emits a RewardConfigUpdated
event with the old and new reward distribution parameters.
Parameters:
rewardsInput
RewardsConfigInput
The proposed referrer address of the caller, e.g. the referral.
removeReward
Disables the reward token as a Lending Pool incentive.
In order to be removed, the reward's emissions must have ended at least 30 days prior, which allows time for removal announcements and gives users time to claim their rewards before removal. If true, then the reward's value is set to false in the _isRewardEnabled
mapping, and the reward is removed from the _rewardsList
.
Upon success, the call emits a RewardRemoved
event with the token's address.
Parameters:
rewardToRemove
address
The address of the reward token
Main External Functions
claimRewards
Claims all accrued and pending rewards for the caller. This function is pausable.
The rewards are cycled through, and the indices for each reward asset and the user are updated via internal calls to _updateRewardData
and _updateUserData
. If the caller does not have any accrued rewards from a reward asset, the function checks the next reward token, reverting if there are no rewards for the caller across all assets.
If the caller has accrued rewards, the reward tokens are sent to msg.sender
, and a RewardsClaimed
event is emitted with the address of the caller, reward vault address, and the claimedAmounts
.
If there are accrued rewards but there are not enough tokens in the reward vault to pay the user their full rewardAmount
, the remaining vault balance will be sent to the user, and the accrued amount decreases by that sent amount. This leaves an accrued balance for the user at the end of the distribution period.
Returns:
rewardsList
address[] memory
The address array of all active rewards.
claimedAmounts
uint256[] memory
The claimed amounts of each reward for the caller, following the rewardsList
order.
relayVaultAction
Relays the changes in USDC deposit amounts from the Pool to the GM Incentives contract for reward calculation and updating.
When users deposit()
or withdraw()
USDC from the Lending Pool, handleTransfer()
on the USDC vault is called, which in turn calls this function. This function can only be called by the USDC vault. If the GM Incentives contract is paused, all logic is bypassed and all contract state remains the same after the call.
The previous USDC amounts of the total pool and the user are used to update the reward and user data. The rewards are cycled through, and the indices for each reward asset and the user are updated via internal calls to _updateRewardData
and _updateUserData
.
If indices are updated, the call emits an Accrued
event with the token's address, the vault's address, the reward indices, and reward tokens accrued.
Parameters:
user
address
The address of the user who initially deposited or withdrew from the Lending Pool
prevUserUSDCDeposits
uint256
The user's previous USDC deposit balance in the pool, prior to the current transaction.
assetAmount
uint256
The user's current amount change in USDC tokens
isDeposit
boolean
If true, action is deposit. If false, action is withdrawal.
Internal Functions
_updateRewardData
Updates the distribution state for all rewards. The newIndex
and totalEmissions
are calculated by _getRewardIndex
. If the oldIndex
and newIndex
are the same, no variables get updated except for rewardData.lastUpdateTimestamp
. If oldIndex
and newIndex
are different, rewardData.index
is updated to the newIndex
and the rewardData.totalSupply
is decreased by totalEmissions
.
Parameters:
rewardData
RewardsDataTypes.RewardData
Storage pointer to the distribution reward config
totalUSDCDeposits
uint256
Current total of underlying assets for this distribution
Returns:
newIndex
uint256
The new distribution index for the reward
indexUpdated
boolean
True if the index was updated, false otherwise.
_updateUserData
Updates the state of the reward distribution for the specific user.
If the newRewardIndex
is the same as the userIndex
, i.e. the user's data is "caught up" with the reward's data, then no rewards are accrued and the dataUpdated
boolean remains false. If the indices differ, dataUpdated
changes to true, and the difference is multiplied by the userAssetBalance
to arrive at rewardsAccrued
. These rewards are added to rewardData.usersData[user].accrued
and an Accrued
event is emitted with new indices and rewardsAccrued
as parameters.
Parameters:
user
address
The address of the user being updated
reward
address
The address of the reward token being updated
rewardData
RewardsDataTypes.RewardData
Storage pointer to the distribution reward config
userAssetBalance
uint256
The user balance of the asset
newRewardIndex
uint256
The new index of the reward asset distribution
Returns:
rewardsAccrued
uint256
The rewards accrued since the last update
dataUpdated
boolean
True if the user's data was updated, false otherwise
_getRewardIndex
Calculates the next reward distribution per deposited USDC token (called "index"), with validations.
The stored reward data for the given token is retrieved. If emissionsPerSecond
is zero, if there is no USDC in the pool, if lastUpdateTimestamp
is set to the current block.timestamp
or is greater than the distributionEnd
, or the totalRewardSupply
has decreased to zero, then the reward Index is not updated, and zero emissions are distributed.
If none of the above is true, the reward distribution per coin of the USDC pool (the "index") is calculated as follows:
If there are not enough rewards for the expected distribution, distribute the remaining rewards across the entire supply.
Parameters:
rewardData
RewardsDataTypes.RewardData
Storage pointer to the distribution reward config
totalUSDCDeposits
uint256
Total amount of USDC deposited in the Lending Pool (includes borrowed USDC)
Returns:
oldIndex
uint256
The previous index of the reward
newIndex
uint256
The previous index plus the newRewardDistribution
totalEmissionsDue
uint256
The total emissions of the current reward token due since the lastUpdateTimestamp
.
Getter Functions
getRewardsList
Retrieves an address array of all currently active rewards.
Returns:
_rewardsList
address[] memory
The list of active rewards/incentives for USDC lending
getRewardsData
Retrieves data for the given reward.
Parameters:
reward
address
The reward token to query
Returns:
rewards[reward].index
uint256
The current index of the reward token
rewards[reward].emissionsPerSecond
uint256
The emitted reward tokens per second
rewards[reward].lastUpdateTimestamp
uint256
The last time the reward token's index was updated.
rewards[reward].distributionEnd
uint256
The timestamp that the reward emissions will end.
rewards[reward].totalSupply
uint256
The total token supply of the reward for the current distribution scheme.
getVaults
Retrieves the USDC and reward tokens vaults.
Returns:
usdcVault
address
The address of the USDC Vault for the GM Lending Pool
rewardsVault
address
The address of the rewards vault
getUserRewardIndex
Retrieves the current index of the given user for the given reward.
Parameters:
user
address
The user to retrieve the index for
reward
address
The reward to retrieve the index for
Returns:
index
uint256
The user's index for the given reward token
getUserAccruedRewards
Retrieves the current accrued reward token amount of the given reward for the given user. When relayVaultAction()
is called (i.e. when a user deposits or withdraws USDC), their pending points are calculated and become accrued.
Parameters:
user
address
The user to retrieve accrued rewards for
reward
address
The reward token address to query
Returns:
accrued
uint256
The accrued reward tokens for the user
getUserUSDCBalance
Retrieves the amount of USDC deposited by the user in the Lending Pool, by calling balanceOf()
on the Pool, with USDC and the user address as arguments.
Parameters:
user
address
The user to query
Returns:
unnamed
uint256
The Lending Pool's USDC balance of the user
getAllUserRewards
Returns a list of all reward amounts for each reward token for a user, including already accrued and unrealized rewards.
Parameters:
user
address
The user to query
Returns:
rewardsList
address[] memory
The list of reward addresses
unclaimedAmounts
uint256[] memory
The list of the accrued yet unclaimed amounts of rewards
pendingAmounts
uint256[] memory
The list of the unrealized, non-accrued amounts of rewards
Last updated