🖨️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
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
InstantiateMsg
This struct holds parameters used to instantiate the Generator contract
owner: String
- Address that can change contract settingsastro_token: String
- ASTRO token contract addresstokens_per_block: Uint128
- Amount of ASTRO distributed per block among all pairsstart_block: Uint64
- Start block for distributing ASTROallowed_reward_proxies: Vec<String>
- Dual rewards proxy contracts allowed to interact with the Generatorvesting_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 ASTROpending_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 tokenproxy_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 blockastro_tokens_per_block: Uint128
- Amount of ASTRO tokens being distributed per block to this LP poollast_reward_block: u64
- The last block when token emissions were snapshotted (distributed)current_block: u64
- Current block number. Useful for computing APRs off-chainaccumulated_rewards_per_share: Decimal
- Total amount of ASTRO rewards already accumulated per LP token stakedpending_astro_rewards: Uint128
- Pending amount of total ASTRO rewards which are claimable by stakers right nowreward_proxy: Option<Addr>
- The address of the 3rd party reward proxy contractpending_proxy_rewards: Option<Uint128>
- Pending amount of total proxy rewards which are claimable by stakers right nowaccumulated_proxy_rewards_per_share: Decimal
- Total amount of 3rd party token rewards already accumulated per LP token stakedproxy_reward_balance_before_update: Uint128
- Reward balance for the dual rewards proxy before updating accrued rewardsorphan_proxy_rewards: Uint128
- The amount of orphan proxy rewards which are left behind by emergency withdrawals and not yet transferred outlp_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 parametersastro_token: Addr
- ASTRO token contract addresstokens_per_block: Uint128
- Total amount of ASTRO distributed per blocktotal_alloc_point: Uint64
- Sum of total allocation points across all active generatorsstart_block: Uint64
- Start block for ASTRO incentivesallowed_reward_proxies: Vec<Addr>
- List of 3rd party reward proxies allowed to interact with the Generator contractvesting_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 addressamount: 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 tokensreward_debt: Uint128
- A reward amount an address already received or that the address is not eligible for; used for proper reward calculationreward_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-zeroalloc_point
last_reward_block: Uint64
- Accumulated amount of rewards per share unit. Used for correct reward calculationsaccumulated_rewards_per_share: Decimal
- This is the accrued amount of rewards up to the latest checkpointreward_proxy: Option
- The 3rd party proxy reward contractaccumulated_proxy_rewards_per_share: Decimal
- This is the accrued amount of 3rd party rewards up to the latest checkpointproxy_reward_balance_before_update: Uint128
- This is the balance of 3rd party proxy rewards that the proxy had before a reward snapshotorphan_proxy_rewards: Uint128
- The orphaned proxy rewards which are left behind by emergency withdrawalshas_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 settingsastro_token: Addr
- The ASTRO token addresstokens_per_block: Uint128
- Total amount of ASTRO rewards per block split between all active generatorstotal_alloc_point: Uint64
- The total (summed up) allocation points for all active generatorsstart_block: Uint64
- The block number when ASTRO mining startedallowed_reward_proxies
- The list of allowed reward proxy contractsvesting_contract: Addr
- The vesting contract from which ASTRO rewards are distributed
Functions
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
pending_token
pending_token(deps: Deps
, env: Env
, lp_token: String
, user: String)
->
Result<PendingTokenResponse
, ContractError>
Calculates and returns pending token rewards for a specific user
query_config
query_config(deps: Deps)
->
Result<ConfigResponse
, ContractError>
Returns information about a generator's configuration
query_reward_info
query_reward_info(deps: Deps
, lp_token: String)
->
Result<RewardInfoResponse
, ContractError>
Returns reward information for a specific generator
query_orphan_proxy_rewards
query_orphan_proxy_rewards(deps: Deps
, lp_token: String)
->
Result<Uint128
, ContractError>
Returns the amount of orphaned proxy rewards for a specific generator
query_pool_info
query_pool_info(deps: Deps
, env: Env
, lp_token: String)
->
Result<PoolInfoResponse
, ContractError>
Returns a generator's configuration
query_simulate_future_reward
query_simulate_future_reward(deps: Deps
, env: Env
, lp_token: String
, future_block: u64)
->
Result<Uint128
, ContractError>
Returns the total amount of ASTRO tokens distributed for a specific generator up to a certain block in the future
query_list_of_stakers
query_list_of_stakers(deps: Deps
, lp_token: String
, start_after: Option<String>
, limit: Option<u32>)
->
Result<Vec<StakerResponse>
, ContractError>
Returns a list of stakers that currently have funds in a specific generator
calculate_rewards
calculate_rewards(env: &Env
, pool: &PoolInfo
, cfg: &Config)
->
StdResult<Uint128>
Calculates and returns the amount of accrued rewards since the last reward checkpoint for a specific generator
3. Reward Distribution
The Generator reward distribution is controlled by several variables:
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_point
s.
4. Walkthrough
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
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
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.
{
"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..."
}
}
Query Functions
deposit
deposit
Returns the amount of a specific LP token that a user currently has staked in the Generator.
{
"deposit": {
"lp_token": "terra...",
"user": "terra..."
}
}
pending_token
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.
{
"pending_token": {
"lp_token": "terra...",
"user": "terra..."
}
}
reward_info
reward_info
{
"reward_info": {
"lp_token": "terra..."
}
}
orphan_proxy_rewards
orphan_proxy_rewards
{
"orphan_proxy_rewards": {
"lp_token": "terra..."
}
}
simulate_future_reward
simulate_future_reward
Returns the amount of ASTRO that will be distributed up to a future block and for a specific LP token.
{
"simulate_future_reward": {
"lp_token": "terra...",
"future_block": "999"
}
}
list_of_stakers
list_of_stakers
Returns a list of stakers that currently have funds in a specific generator.
{
"list_of_stakers": {
"lp_token": "terra...",
"start_after": "terra...",
"limit": 5
}
}
5. Risks
alloc_point
miscalculation can lead to specific pools not getting the initially intended ASTRO emissions.If
owner
is compromised, it can drain the Generator of all staked LP tokens.Dual rewards proxy misconfiguration can block addresses from staking in specific generators.
Last updated
Was this helpful?