Andromeda
Search…
CW20 Staking

Introduction

This contract allows users to stake a specified token and to receive rewards in any number of other tokens in proportion to their share. The reward token does not need to be the token they stake with but it can be. The contract allows for two types of rewards:
  • non-allocated rewards: These are rewards that get deposited periodically into the contract and get distributed proportionally to stakers. Rewards that are deposited are instantly granted to the stakers.
  • Allocated rewards: The owner deposits a number of tokens to be distributed over the course of a set time. The rewards get distributed the same way, except all of the reward tokens are already deposited in the contract.
The added rewards are distributed proportionally between the stakers that are already staked.

Example

We assume that we instantiated the contract and there are no stakers as of yet. Then the following series of events happen:
  1. 1.
    First user stakes 100 tokens
  2. 2.
    Second user stakes 500 tokens
  3. 3.
    Third user stakes 400 tokens
  4. 4.
    100 tokens are sent to the contract as rewards
  5. 5.
    Fourth user stakes 1000 tokens
  6. 6.
    1000 tokens are sent as rewards
In this case, when the 100 coins are sent the pending rewards are as following for each user:
  • 10 tokens for user 1
  • 50 tokens for user 2
  • 40 tokens for user 3
  • 0 tokens for user 4 since he staked after the rewards were sent
After the 1000 tokens are sent to the contract as rewards, it is split as follows:
  • 50 tokens for user 1 (60 in total)
  • 250 tokens for user 2 (300 in total)
  • 200 tokens for user 3 (240 in total)
  • 500 tokens for user 4 (500 in total since did not receive rewards from first batch)
After the rewards have been sent, the stakers would not receive any extra rewards until a next batch of rewards are sent.
Ado_type: cw20-staking

InstantiateMsg

The additional rewards should not include the staking token.
Rust
JSON
pub struct InstantiateMsg {
pub staking_token: AndrAddress,
pub additional_rewards: Option<Vec<RewardTokenUnchecked>>,
}
{
"staking_token":{
"identifier":"juno1..."
},
"additional_rewards": [{
"asset_info":{
"cw-20":"juno1..."
},
"allocation_config":{
"init_timestamp": 104329432,
"till_timestamp": 104334432,
"cycle_rewards":"300",
"cycle duration":"400"
}
}]
}
Name
Type
Description
staking_token
The cw20 token that can be staked
additional_rewards
Option<Vec<RewardTokenUnchecked>>
Any rewards in addition to the staking token. This list cannot include the staking token since it is used as a reward by default. Can have a maximum of 10 reward tokens.

RewardTokenUnchecked

pub struct RewardTokenUnchecked {
pub asset_info: AssetInfoUnchecked,
pub allocation_config: Option<AllocationConfig>,
}
Name
Type
Description
asset_info
AssetInfoUnchecked
The asset used as a reward.
allocation_config
How to allocate the asset_info as rewards. If not set, then the rewards are of the "non-allocated" type.

AssetInfoUnchecked

pub type AssetInfoUnchecked = AssetInfoBase<String>

AssetInfoBase

pub enum AssetInfoBase<T> {
Cw20(T),
Native(String),
}
  • Cw20: To create an asset info instance of this type, provide the contract address.
  • Native: To create an asset info instance of this type, provide the denomination.

AllocationConfig

pub struct AllocationConfig {
pub init_timestamp: u64,
pub till_timestamp: u64,
pub cycle_rewards: Uint128,
pub cycle_duration: u64,
pub reward_increase: Option<Decimal>,
}
Name
Type
Description
init_timestamp
u64
Timestamp from which Rewards will start getting accrued against the staked LP tokens.
till_timestamp
u64
Timestamp till which Rewards will be accrued. No staking rewards are accrued beyond this timestamp.
cycle_rewards
Uint128
Rewards distributed during the 1st cycle.
cycle_duration
u64
Cycle duration in seconds.
reward_increase
Optional<Decimal>
Percent increase in Rewards per cycle.

ExecuteMsg

Receive

Receives Cw-20 tokens which can be staked, or used to update the global index depending on the attached Cw20HookMsg
pub enum ExecuteMsg {
Receive(Cw20ReceiveMsg),
}

Cw20ReceiveMsg

pub struct Cw20ReceiveMsg {
pub sender: String,
pub amount: Uint128,
pub msg: Binary,
}
The msg in the Cw20ReceiveMsgshould be a Cw20HookMsg.

Cw20HookMsg

pub enum Cw20HookMsg {
StakeTokens {},
UpdateGlobalIndex {},
}
StakeTokens: Stake the sent tokens. Address must match the staking_token given on instantiation. The user's pending rewards and indexes are updated for each additional reward token.
UpdateGlobalIndex: Updates the global reward index on deposit of a valid cw20 token.

AddRewardToken

Add reward_token as another reward token. A maximum of 10 reward tokens can be added.
Only available to the contract owner/operator.
Rust
JSON
pub enum ExecuteMsg {
AddRewardToken {
reward_token: RewardInfoUnchecked,
},
}
{
"add_reward_token":{
"reward_token":{
"cw20":"juno1..."
}
}
}
Name
Type
Description
reward_token
The token to be added as a reward.

UnstakeTokens

Unstakes the specified amount of assets, or all if not specified. The user's pending rewards and indexes are updated for each additional reward token.
Rust
JSON
pub enum ExecuteMsg {
UnstakeTokens {
amount: Option<Uint128>,
},
}
{
"unstake_tokens":{
"amount":"500"
}
}
Name
Type
Description
amount
Option<Uint128>
Optional amount to unstake. Defaults to the maximum amount.

ClaimRewards

Claims any outstanding rewards from the additional reward tokens.
Rust
JSON
pub enum ExecuteMsg {
ClaimRewards {},
}
{
"claim_rewards":{}
}

UpdateGlobalIndexes

Updates the global reward index for the specified assets or all of the specified ones if none is specified. Funds may be sent along with this. Usually called when new allocated rewards are deposited to update the rewards accordingly.
Rust
JSON
pub enum ExecuteMsg {
UpdateGlobalIndexes {
asset_infos: Option<Vec<AssetInfoUnchecked>>,
},
}
"update_global_indexes":{}
Name
Type
Description
asset_infos
Option<Vec<AssetInfoUnchecked>>
Optional vector to specify the assets to update the global index for.

AndrReceive

QueryMsg

Config

Gets the config of the contract.
Rust
JSON
pub enum QueryMsg {
Config {},
}
{
"config":{}
}

Config

Returns the config structure.
Rust
JSON
pub struct Config {
pub staking_token: AndrAddress,
pub number_of_reward_tokens: u32,
}
{
"staking_token":{
"identifier":"juno1..."
},
"number_of_rewards_tokens": 7
}
Name
Type
Description
staking_token
The token accepted for staking.
number_of_reward_tokens
u32
The current number of reward tokens, cannot exceed the maximum of 10.

State

Gets the state of the contract.
Rust
JSON
pub enum QueryMsg {
State {},
}
{
"state":{}
}

State

Returns the State structure.
Rust
JSON
pub struct State {
pub total_share: Uint128,
}
{
"total_share":"1000"
}
Name
Type
Description
total_share
Uint128
The total share/amount of the staking token in the contract.

Staker

Returns a StakerResponse for the given staker. The pending rewards are updated to the present index.
Rust
JSON
pub enum QueryMsg {
Staker {
address: String,
},
}
{
"staker":{
"address":"juno1..."
}
}
Name
Type
Description
address
String
The address of the staker to check

StakerResponse

Rust
JSON
pub struct StakerResponse {
pub address: String,
pub share: Uint128,
pub balance: Uint128,
pub pending_rewards: Vec<(String, Uint128)>,
}
{
"address": "juno1...",
"share": "10000000",
"pending_rewards": [
[
"native:uusd",
"6666666"
]
]
}
Name
Type
Description
address
String
The address of the staker.
share
Uint128
The staker's share of the staked tokens.
balance
Uint128
How many staking tokens the user has which is the staked amount + rewarded tokens.
pending_rewards
Vec<(String,Uint)>
The staker's pending rewards represented as [(token_1, amount_1), ..., (token_n, amount_n)]

Stakers

Returns a Vec<StakerResponse> for range of stakers. The pending rewards are updated to the present index for each staker.
Rust
JSON
pub enum QueryMsg {
Stakers {
start_after: Option<String>,
limit: Option<u32>,
},
}
{
"stakers":{
"limit":20
}
}
start_after
Option<String>
An optional ID to start after. Used for pagination.
limit
Optional<u32>
An optional limit to the number of stakers to query. Defaults to 10 and can be set to a maximum of 30.
Returns a vector of StakerResponse.

Timestamp

Queries the current timestamp in seconds.
Rust
JSON
pub enum QueryMsg {
Timestamp {},
}
}
{
"timestamp":{}
}
Returns a u64 with the current timestamp in seconds.

AndrQuery

Check AndrQuery.
Copy link
Outline
Introduction
InstantiateMsg
ExecuteMsg
Receive
AddRewardToken
UnstakeTokens
ClaimRewards
UpdateGlobalIndexes
AndrReceive
QueryMsg
Config
State
Staker
Stakers
Timestamp
AndrQuery