Astroport
Search…
πŸ–¨
Generator
Contract that distributes ASTRO emissions to LP stakers and allows other teams to incentivize their pairs

1. Overview

The Generator contract distributes token rewards (ASTRO) based on locked LP token amounts for each eligible Astroport pool. The Generator also supports proxy staking via 3rd party contracts so that stakers can receive dual rewards.
The Generator contract code can be found here.

2. Variables & Functions

Constants

Name
Description
CONFIG
Stores the contract configuration
POOL_INFO
Contains information about all generators
TMP_USER_ACTION
Used to temporarily store data about a user action
USER_INFO
Stores information about all stakers in every generator
MAX_LIMIT
The maximum amount of users that can be read at once from USER_INFO
DEFAULT_LIMIT
The default amount of users to read from USER_INFO
OWNERSHIP_PROPOSAL
Contains the proposal to change contract ownership
CONTRACT_NAME
Contract name
CONTRACT_VERSION
Contract version

Structs

Name
Description
Contains
InstantiateMsg
This struct holds parameters used to instantiate the Generator contract
  • owner: String - Address that can change contract settings
  • astro_token: String - ASTRO token contract address
  • tokens_per_block: Uint128 - Amount of ASTRO distributed per block among all pairs
  • start_block: Uint64 - Start block for distributing ASTRO
  • allowed_reward_proxies: Vec<String> - Dual rewards proxy contracts allowed to interact with the Generator
  • vesting_contract: String - The ASTRO vesting contract that drips ASTRO rewards
PoolLengthResponse
This structure holds the response returned when querying the total length of the array that keeps track of instantiated generators
  • length: usize - The total length of the generator array
PendingTokenResponse
This structure holds the response returned when querying the amount of pending rewards that can be withdrawn from a 3rd party rewards contract
  • pending: Uint128 - The amount of pending ASTRO
  • pending_on_proxy: Option<Uint128> - The amount of pending 3rd party reward tokens
RewardInfoResponse
This structure holds the response returned when querying for the token addresses used to reward a specific generator
  • base_reward_token: Addr - The address of the base reward token
  • proxy_reward_token: Option<Addr> - The address of the 3rd party reward token
PoolInfoResponse
This structure holds the response returned when querying for a pool's information
  • alloc_point: Uint64 - The slice of ASTRO that this pool's generator gets per block
  • astro_tokens_per_block: Uint128 - Amount of ASTRO tokens being distributed per block to this LP pool
  • last_reward_block: u64 - The last block when token emissions were snapshotted (distributed)
  • current_block: u64 - Current block number. Useful for computing APRs off-chain
  • accumulated_rewards_per_share: Decimal - Total amount of ASTRO rewards already accumulated per LP token staked
  • pending_astro_rewards: Uint128 - Pending amount of total ASTRO rewards which are claimable by stakers right now
  • reward_proxy: Option<Addr> - The address of the 3rd party reward proxy contract
  • pending_proxy_rewards: Option<Uint128> - Pending amount of total proxy rewards which are claimable by stakers right now
  • accumulated_proxy_rewards_per_share: Decimal - Total amount of 3rd party token rewards already accumulated per LP token staked
  • proxy_reward_balance_before_update: Uint128 - Reward balance for the dual rewards proxy before updating accrued rewards
  • orphan_proxy_rewards: Uint128 - The amount of orphan proxy rewards which are left behind by emergency withdrawals and not yet transferred out
  • lp_supply: Uint128 - Total amount of lp tokens staked in the pool's generator
ConfigResponse
This structure holds the response returned when querying the contract for general parameters
  • owner: Addr - Address that's allowed to change contract parameters
  • astro_token: Addr - ASTRO token contract address
  • tokens_per_block: Uint128 - Total amount of ASTRO distributed per block
  • total_alloc_point: Uint64 - Sum of total allocation points across all active generators
  • start_block: Uint64 - Start block for ASTRO incentives
  • allowed_reward_proxies: Vec<Addr> - List of 3rd party reward proxies allowed to interact with the Generator contract
  • vesting_contract: Addr - The ASTRO vesting contract address
StakerResponse
This structure holdes the parameters used to return information about a staked in a specific generator
  • account: String - The staker's address
  • amount: Uint128 - The amount that the staker currently has in the generator
UserInfo
This structure provides information for an address staked in a specific generator
  • amount: Uint128 - An amount of staked LP tokens
  • reward_debt: Uint128 - A reward amount an address already received or that the address is not eligible for; used for proper reward calculation
  • reward_debt_proxy: Uint128 - Proxy reward amount an address already received or is not eligible for; used for proper reward calculation
PoolInfo
This structure provides information for a pool
  • alloc_point: Uint64 - Allocation points are used to control reward distribution among eligible pools; a pool is eligible is its generator has a non-zero alloc_point
  • last_reward_block: Uint64 - Accumulated amount of rewards per share unit. Used for correct reward calculations
  • accumulated_rewards_per_share: Decimal - This is the accrued amount of rewards up to the latest checkpoint
  • reward_proxy: Option - The 3rd party proxy reward contract
  • accumulated_proxy_rewards_per_share: Decimal - This is the accrued amount of 3rd party rewards up to the latest checkpoint
  • proxy_reward_balance_before_update: Uint128 - This is the balance of 3rd party proxy rewards that the proxy had before a reward snapshot
  • orphan_proxy_rewards: Uint128 - The orphaned proxy rewards which are left behind by emergency withdrawals
  • has_asset_rewards: bool - Whether a generator receives 3rd party rewards or not
Config
This structure returns the main configuration for the Generator contract
  • owner: Addr - Address used to change contract settings
  • astro_token: Addr - The ASTRO token address
  • tokens_per_block: Uint128 - Total amount of ASTRO rewards per block split between all active generators
  • total_alloc_point: Uint64 - The total (summed up) allocation points for all active generators
  • start_block: Uint64 - The block number when ASTRO mining started
  • allowed_reward_proxies - The list of allowed reward proxy contracts
  • vesting_contract: Addr - The vesting contract from which ASTRO rewards are distributed

Functions

Function
Params
Description
instantiate
(deps: DepsMut, _env: Env, _info: MessageInfo, msg: InstantiateMsg) -> <Response, ContractError>
Initializes the generator contract using provided parameters
execute
(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> Result<Response, ContractError>
Exposes execute functions available in the contract
execute_update_config
execute_update_config(deps: DepsMut, info: MessageInfo, vesting_contract: Option<String>) -> Result<Response, ContractError>
Sets a new Generator vesting contract address
add
add(mut deps: DepsMut, env: Env, lp_token: Addr, alloc_point: Uint64, has_asset_rewards: bool, reward_proxy: Option<String>) -> Result<Response, ContractError>
Creates a new generator and adds it to POOL_INFO (if it does not exist yet) and updates total allocation points (in Config)
set
set(mut deps: DepsMut, env: Env, lp_token: Addr, alloc_point: Uint64, has_asset_rewards: bool) -> Result<Response, ContractError>
Updates the given generator's ASTRO allocation points
reply
reply(deps: DepsMut, env: Env, _msg: Reply) -> Result<Response, ContractError>
The entry point to the contract for processing replies from submessages
mass_update_pools
mass_update_pools(mut deps: DepsMut, env: Env) -> Result<Response, ContractError>
Updates the amount of accrued rewards for all generators
update_pool
update_pool(mut deps: DepsMut, env: Env, lp_token: Addr) -> Result<Response, ContractError>
Updates the amount of accrued rewards for a specific generator
accumulate_rewards_per_share
accumulate_rewards_per_share(deps: DepsMut, env: &Env, lp_token: &Addr, pool: &mut PoolInfo, cfg: &Config, deposited: Option<Uint128>) -> StdResult<()>
Accrues the amount of rewards distributed for each staked LP token in a specific generator. Update reward variables for the given generator
receive_cw20
(deps: DepsMut, env: Env, info: MessageInfo, cw20_msg: Cw20ReceiveMsg) -> Result<Response, ContractError>
Receives a message of type [Cw20ReceiveMsg] and processes it depending on the received template
send_pending_rewards
send_pending_rewards(cfg: &Config, pool: &PoolInfo, user: &UserInfo, to: &Addr) -> Result<Vec, ContractError>
Distributes pending proxy rewards for a specific staker
deposit
deposit(mut deps: DepsMut, env: Env, lp_token: Addr, beneficiary: Addr, amount: Uint128) -> Result<Response, ContractError>
Deposit LP tokens in a generator to receive token emissions
withdraw
withdraw(mut deps: DepsMut, env: Env, lp_token: Addr, account: Addr, amount: Uint128) -> Result<Response, ContractError>
Withdraw LP tokens from a generator
emergency_withdraw
emergency_withdraw(deps: DepsMut, _env: Env, info: MessageInfo, lp_token: String) -> Result<Response, ContractError>
Withdraw LP tokens without caring about rewards. To be used in emergency cases only
set_allowed_reward_proxies
set_allowed_reward_proxies(deps: DepsMut, info: MessageInfo, proxies: Vec<String>) -> Result<Response, ContractError>
Sets the allowed reward proxies that can interact with the Generator contract
send_orphan_proxy_rewards
send_orphan_proxy_rewards(deps: DepsMut, info: MessageInfo, recipient: String, lp_token: String) -> Result<Response, ContractError>
Sends orphaned proxy rewards (which are left behind by emergency withdrawals) to another address. Can only be called by the owner
migrate
migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result<Response, ContractError>
Used for contract migration
query
query(deps: Deps, env: Env, msg: QueryMsg) -> Result<Binary, ContractError>
Exposes all the queries available in the contract
pool_length
pool_length(deps: Deps) -> Result<PoolLengthResponse, ContractError>
Returns the amount of instantiated generators
query_deposit
query_deposit(deps: Deps, lp_token: String, user: String) -> Result<Uint128, ContractError>
Returns the amount of LP tokens a user staked in a specific generator

3. Reward Distribution

The Generator reward distribution is controlled by several variables:
Variable
Description
tokens_per_block
The total amount of ASTRO rewards that will be distributed every block among all active generators
alloc_point
A distribution ratio set per individual generator
total_alloc_point
The sum of alloc_point for each active generator
The formula for reward distribution (for every generator) is the following:
astro_to_distribute = blocks_since_last_reward * tokens_per_block * alloc_point / total_alloc_point
For example, if there are three active generators, and the alloc_point for each generator is 1000, the total_alloc_point would equal 3000 (1000 * 3). All three pools will get an equal amount of rewards. But what happens if we want to add another pool? Let's add one more pool and set its alloc_point to 3000.
Note, that doing this will change the distribution for all existing pools, as it will affect the total_alloc_point variable. After adding the new pool, the total_alloc_point would be 6000. This new pool will now receive 50% of rewards (3000 is 50% of 6000) and the other 50% will be evenly distributed between the initial three pools (because each of their alloc_points is 1000). In order to maintain the same reward allocations for existing pools, it is required to update each of their alloc_points.

4. Walkthrough

The following are examples and descriptions of core functions that can be called by anyone to interact with the Generator contract.

Execute Functions

deposit
Stakes LP tokens in a specific generator (inside the Generator contract). In order to stake in the Generator contract, you should execute this message inside the contract of the LP token you want to stake.
{
"send": {
"contract": <GeneratorContractAddress>,
"amount": 999,
"msg": "base64-encodedStringOfWithdrawMsg"
}
}
Inside send.msg, you may encode this JSON string into base64 encoding:
{
"Deposit": {}
}

depositFor

Stakes LP tokens in the Generator on behalf of another address. In order to stake in the Generator contract, you should execute this message inside the LP token you want to stake.
{
"send": {
"contract": <GeneratorContractAddress>,
"amount": 999,
"msg": "base64-encodedStringOfWithdrawMsg"
}
}
In send.msg, you may encode this JSON string into base64 encoding:
{
"DepositFor": "terra..."
}
withdraw
Unstakes LP tokens from the Generator contract and claims outstanding token emissions. An address can also claim rewards without unstaking from a generator: call the withdraw function and specify amount as 0 (you don’t withdraw any LP tokens, only claim rewards).
"withdraw": {
"lp_token": "terra...",
"amount": "123"
}
}

emergency_withdraw

Unstakes LP tokens without caring about rewards. To be used only in emergencies such as a critical bug found in the Generator contract.
{
"emergency_withdraw": {
"lp_token": "terra..."
}
}
auto_stake
An address can provide liquidity and stake in the Generator in one transaction using the Swap Pairs contracts. Calling the provide_liquidity operation with auto_stake astrue allows LP tokens to automatically be staked in the Generator contract (if the LP tokens currently get ASTRO or 3rd party emissions). If auto_stake is not specified, LP tokens will just be minted for the recipient.
ANC-UST
bLUNA-LUNA
{
"provide_liquidity": {
"assets": [
{
"info": {
"token": {
"contract_addr": "terra14z56l0fp2lsf86zy3hty2z47ezkhnthtr9yq76"
}
},
"amount": "1000000"
},
{
"info": {
"native_token": {
"denom": "uusd"
}
},
"amount": "1000000"
}
],
"slippage_tolerance": "0.01",
"auto_stake": true,
"receiver": "terra..."
}
}
{
"provide_liquidity": {
"assets": [
{
"info": {
"token": {
"contract_addr": "terra1kc87mu460fwkqte29rquh4hc20m54fxwtsx7gp"
}
},
"amount": "1000000"
},
{
"info": {
"native_token": {
"denom": "uluna"
}
},
"amount": "1000000"
}
],
"slippage_tolerance": "0.01",
"auto_stake": true,
"receiver": "terra..."
}
}

Query Functions

deposit

Returns the amount of a specific LP token that a user currently has staked in the Generator.
Query
Ex. Response
{
"deposit": {
"lp_token": "terra...",
"user": "terra..."
}
}
"123"

pending_token

Returns the amount of pending ASTRO and 3rd party token rewards that can be claimed by a user that staked a specific LP token.
Query
Ex. Response
{
"pending_token": {
"lp_token": "terra...",
"user": "terra..."
}
}
{
"pending": "123",
"pending_on_proxy": null
}

reward_info

Query
ANC-UST Ex. Response
{
"reward_info": {
"lp_token": "terra..."
}
}
{
"base_reward_token": "terra1xj49zyqrwpv5k928jwfpfy2ha668nwdgkwlrg3",
"proxy_reward_token": "terra14z56l0fp2lsf86zy3hty2z47ezkhnthtr9yq76"
}

orphan_proxy_rewards

Query
ANC-UST Ex. Response
{
"orphan_proxy_rewards": {
"lp_token": "terra..."
}
}
"0"

simulate_future_reward

Returns the amount of ASTRO that will be distributed up to a future block and for a specific LP token.
Query
Ex. Response
{
"simulate_future_reward": {
"lp_token": "terra...",
"future_block": "999"
}
}
"123"

list_of_stakers

Returns a list of stakers that currently have funds in a specific generator.
Query
{
"list_of_stakers": {
"lp_token": "terra...",
"start_after": "terra...",
"limit": 5
}
}

5. Risks

  1. 1.
    alloc_point miscalculation can lead to specific pools not getting the initially intended ASTRO emissions.
  2. 2.
    If owner is compromised, it can drain the Generator of all staked LP tokens.
  3. 3.
    Dual rewards proxy misconfiguration can block addresses from staking in specific generators.