Safety Module / stkAAVE

The AAVE token can also be staked in the Safety Module, a core part of Aavenomics. By staking AAVE in the Safety Module, users help protect the protocol from a short fall event and earn an incentive as a result.

This section will cover the technical aspects of staking and the Safety Module. For governance, security, and incentive details, see the Aavenomics documentation.

The source code for the Safety Module, which includes the Staked AAVE token, can be found on Github here.

Deployed Contracts

When integrating, only the proxy contracts should be used.

The following are the current implementation of the contracts, which may be subject to change. Therefore always integrate the above proxy contracts only.


Integrating Staking

To perform AAVE staking in your integration, the following steps should be followed:

1. Ensure your users have AAVE

If they still have LEND, then the LEND tokens need to be migrated. See the LEND to AAVE migration guide.

2. Stake the user's AAVE

  1. The user must first approve() the amount for the Staked AAVE contract to stake.

  2. The user should call stake(), passing in their address and the amount to stake.

3. Claim staking rewards

After a period of time, the user will accrue rewards. To check the rewards accrued for a certain user, call getTotalRewardsBalance() to fetch the pending rewards. To claim the rewards, call claimRewards().

4. Un-staking

To un-stake, a user must first activate the cool down timer, wait for the cool down time to elapse, then redeem their staked tokens.

  1. To activate the cool down timer, call cooldown().

  2. To check if the cool down timer has finished, the current unix timestamp must be greater than the value returned from stakersColldowns() + COOLDOWN_SECONDS().

  3. When the cool down has finished, the user will have a maximum UNSTAKE_WINDOW() of time to redeem their tokens. If they do not redeem before this time period has elapsed, then the cool down timer is reset and they will need to activate the cool down again.

  4. The final step to un-stake it to call redeem().

Staked AAVE (stkAAVE)

When a user stakes AAVE in the Safety Module, the user receives an equivalent amount of stkAAVE in return, and starts accruing rewards in AAVE. The user is then able to claim the rewards at anytime. To withdraw their staked AAVE, the user needs to activate a coolDown() period, as detailed below.


function stake(address onBehalfOf, uint256 amount) - code

Stakes a certain amount of AAVE tokens, with the option of sending the staked AAVE tokens (stkAAVE) to another address (i.e. the onBehalfOf address).

Note: the msg.sender must already have a balance of AAVE token.

The user must approve() the amount for the Staked AAVE contract to stake, before execution.


function claimRewards(address to, uint256 amount) - code

Claims an amount of AAVE rewards that the msg.sender has accrued, with the option of sending the rewards to a different account.


function redeem(address to, uint256 amount) - code

Redeems the staked tokens - receiving AAVE tokens and burning stkAAVE tokens.

A user can only redeem the underlying AAVE tokens if the following has been satisfied:

  1. Activated their cooldown() period, and

  2. The sum of stakersCooldowns() + COOLDOWN_SECONDS() for their address must be greater than the current unix block timestamp, and

  3. They must call redeem() before the sum of stakersCooldowns() + COOLDOWN_SECONDS() +UNSTAKE_WINDOW() has passed.


function cooldown() - code

Activates the cool down timer to be able to unstake.

See getNextCooldownTimestamp() for example cool down periods and scenarios.


function stakersCooldowns(address staker) view returns uint - code

Returns the unix timestamp in seconds for when the staker activated the cool down by calling cooldown().

A staker is able to successfully unstake when this value + COOLDOWN_SECONDS in unix time has passed.


function COOLDOWN_SECONDS() view returns uint - code

Returns the current minimum cool down time needed to elapse before a staker is able to unstake their tokens.

As of October 2020, the current COOLDOWN_SECONDS value is 864000 seconds (i.e. 10 days). This value should always be checked directly from the contracts.


function UNSTAKE_WINDOW() view returns uint - code

Returns the maximum window of time in seconds that a staker can redeem() their stake once a cooldown() period has been completed.

As of October 2020, the current UNSTAKE_WINDOW value is 172800 seconds (i.e. 2 days). This value should always be checked directly from the contracts.


function getNextCooldownTimestamp(uint256 fromCooldownTimestamp, uint256 amountToReceive, address toAddress, uint256 toBalance) public returns (uint256) - code

Calculates the cool down timestamp based on the sender / receiver timestamps.

Cool down examples:

  • A user stakes AAVE for the first time. Their cool down time is set to the current block timestamp.

  • A user already has stkAAVE and decides to stake more AAVE (i.e. call stake()), while they already have a cool down period active:

    • If the cool down is expired (e.g. beyond the UNSTAKE_WINDOW), then the cool down period will remain expired.

    • If the cool down period is still valid, using the amount staked and and the current block timestamp, a weighted average is calculated with the current cool down timestamp of the user.

  • A user calls redeem(). This will reset the cool down timestamp.

  • A user calls claimRewards(). The cool down timestamp is not affected.

  • A user transfers (i.e. sends) stkAAVE to another address:

    • The cool down timestamp of the msg.sender remains the same.

    • For the receiver of the stkAAVE:

      • If they have a valid cool down period finishing before the cool down period of the msg.sender, a weighted average is calculated with the current cool down timestamp of the user.

      • If the receiver has an expired cool down timestamp, the cool down timestamp is reset.

      • If both the receiver and msg.sender have valid cool down periods, and the msg.sender cool down period ends before the receiver, then the receiver's cool down period remains the same.


function getTotalRewardsBalance(address staker) external view returns (uint256) - code

Returns the total rewards that are pending to be claimed by a staker.

Last updated