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

Mainnet
Kovan
Mainnet

When integrating, only the proxy contracts should be used.

Proxy Contracts

Interface

Address and ABIs

Staked AAVE (stkAAVE)

Solidity

0x4da27a545c0c5B758a6BA100e3a049001de870f5

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

Implementations

Address and ABI

Staked AAVE (stkAAVE)

0x74A7A4e7566a2f523986e500cE35b20d343F6741

Kovan

When integrating, only the proxy contracts should be used.

Proxy Contracts

Interface

Address and ABIs

Staked AAVE (stkAAVE)

Solidity

0xf2fbf9A6710AfDa1c4AaB2E922DE9D69E0C97fd2

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

Implementations

Address and ABI

Staked AAVE (stkAAVE)

TBC

Audits

Auditor

Audit Type

Consensys Diligence (Safety Module / Staked AAVE)

Smart Contract

CertiK (Safety Module / Staked AAVE)

Smart Contract

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.

stake()

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.

Parameter

Type

Description

onBehalfOf

address

The address which will receive the stkAAVE tokens. Use msg.sender if the stkAAVE should be sent to the same calling address.

amount

uint256

The amount of AAVE to be staked

claimRewards()

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.

Parameter

Type

Description

to

address

The address which will receive the AAVE tokens rewards. Use msg.sender if the AAVE rewards should be sent to the same calling address.

amount

uint256

The amount of AAVE to be claimed. Use uint(-1) to claim all outstanding rewards for the user.

redeem()

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() + UNSTAKE_WINDOW() has passed.

Parameter

Type

Description

to

address

The address which will receive the redeemed AAVE tokens. Use msg.sender if the AAVE should be sent to the same calling address.

amount

uint256

The amount of AAVE to be redeemed. Use uint(-1) to redeem the entire balance of the user.

cooldown()

function cooldown() - code

Activates the cool down timer to be able to unstake.

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

stakersCooldowns()

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.

COOLDOWN_SECONDS()

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.

UNSTAKE_WINDOW()

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.

getNextCooldownTimestamp()

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.

Parameter

Type

Description

fromCooldownTimestamp

uint256

The cool down timestamp of the sender

amountToReceive

uint256

The amount of stkAAVE tokens to be sent

toAddress

address

The receiver's address

toBalance

uint256

The current stkAAVE balance of the receiver

getTotalRewardsBalance()

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

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

Parameter

Type

Description

staker

address

The staker's address