Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vxASTRO): remove max pool limit; vote once per epoch; privileged instant unlock #111

Merged
merged 7 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified assets/emissions_controller_general.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion contracts/emissions_controller/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "astroport-emissions-controller"
version = "1.0.0"
version = "1.0.1"
authors = ["Astroport"]
edition = "2021"
description = "Astroport vxASTRO Emissions Voting Contract"
Expand Down
3 changes: 2 additions & 1 deletion contracts/emissions_controller/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ If the pool is located on the Hub contract also checks, this LP token correspond
## Voting

Users are required to have vxASTRO to cast their votes.
They can vote for up to five whitelisted pools at once every 10 days.
They can vote for whitelisted pools at once every epoch.
Vote changes are not allowed after votes are cast.
After voting, they can't change their votes until the cooldown period ends.
Executable message accepts an array of tuples with LP token and vote weight.
Vote weight is a number between 0 and 1. Total vote weight can't exceed 1.
Expand Down
8 changes: 3 additions & 5 deletions contracts/emissions_controller/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ use cw_utils::{ParseReplyError, PaymentError};
use neutron_sdk::NeutronError;
use thiserror::Error;

use astroport_governance::emissions_controller::consts::MAX_POOLS_TO_VOTE;

/// This enum describes contract errors
#[derive(Error, Debug, PartialEq)]
pub enum ContractError {
Expand Down Expand Up @@ -65,9 +63,6 @@ pub enum ContractError {
#[error("Failed to determine outpost for pool {0}")]
NoOutpostForPool(String),

#[error("You can vote maximum for {MAX_POOLS_TO_VOTE} pools")]
ExceededMaxPoolsToVote {},

#[error("Message contains duplicated pools")]
DuplicatedVotes {},

Expand All @@ -79,4 +74,7 @@ pub enum ContractError {

#[error("Can't set zero emissions for astro pool")]
ZeroAstroEmissions {},

#[error("Failed to migrate contract")]
MigrationError {},
}
18 changes: 7 additions & 11 deletions contracts/emissions_controller/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ use itertools::Itertools;
use neutron_sdk::bindings::msg::NeutronMsg;
use neutron_sdk::bindings::query::NeutronQuery;

use astroport_governance::emissions_controller::consts::{
EPOCH_LENGTH, IBC_TIMEOUT, MAX_POOLS_TO_VOTE, VOTE_COOLDOWN,
};
use astroport_governance::emissions_controller::consts::{EPOCH_LENGTH, IBC_TIMEOUT};
use astroport_governance::emissions_controller::hub::{
AstroPoolConfig, HubMsg, OutpostInfo, OutpostParams, OutpostStatus, TuneInfo, UserInfo,
VotedPoolInfo,
Expand Down Expand Up @@ -53,10 +51,6 @@ pub fn execute(
votes.len() == votes_map.len(),
ContractError::DuplicatedVotes {}
);
ensure!(
votes_map.len() <= MAX_POOLS_TO_VOTE,
ContractError::ExceededMaxPoolsToVote {}
);
let deps = deps.into_empty();
let config = CONFIG.load(deps.storage)?;
let voting_power = get_voting_power(deps.querier, &config.vxastro, &info.sender, None)?;
Expand Down Expand Up @@ -415,7 +409,7 @@ pub fn retry_failed_outposts(
}

/// The function checks that:
/// * user didn't vote for the last 10 days,
/// * user didn't vote at the current epoch,
/// * sum of all percentage values <= 1.
/// User can direct his voting power partially.
///
Expand All @@ -434,10 +428,12 @@ pub fn handle_vote(
) -> Result<Response<NeutronMsg>, ContractError> {
let user_info = USER_INFO.may_load(deps.storage, voter)?.unwrap_or_default();
let block_ts = env.block.time.seconds();
// Is the user eligible to vote again?

let epoch_start = get_epoch_start(block_ts);
// User can vote once per epoch
ensure!(
user_info.vote_ts + VOTE_COOLDOWN <= block_ts,
ContractError::VoteCooldown(user_info.vote_ts + VOTE_COOLDOWN)
user_info.vote_ts < epoch_start,
ContractError::VoteCooldown(epoch_start + EPOCH_LENGTH)
);

let mut total_weight = Decimal::zero();
Expand Down
9 changes: 6 additions & 3 deletions contracts/emissions_controller/src/ibc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,10 @@ mod unit_tests {
POOLS_WHITELIST
.save(deps.as_mut().storage, &vec!["osmo1pool1".to_string()])
.unwrap();
let env = mock_env();

let mut env = mock_env();
env.block.time = Timestamp::from_seconds(1724922008);

VOTED_POOLS
.save(
deps.as_mut().storage,
Expand All @@ -404,12 +407,12 @@ mod unit_tests {
let ack_err: IbcAckResult = from_json(resp.acknowledgement).unwrap();
assert_eq!(ack_err, IbcAckResult::Ok(b"ok".into()));

// The same user has voting cooldown for 10 days
// The same user can only vote at the next epoch
let resp = ibc_packet_receive(deps.as_mut().into_empty(), env.clone(), ibc_msg).unwrap();
let ack_err: IbcAckResult = from_json(resp.acknowledgement).unwrap();
assert_eq!(
ack_err,
IbcAckResult::Error("Next time you can change your vote is at 1572661419".to_string())
IbcAckResult::Error("Next time you can change your vote is at 1725840000".to_string())
);

// Voting from random channel is not possible
Expand Down
1 change: 1 addition & 0 deletions contracts/emissions_controller/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod state;
pub mod error;
pub mod ibc;
pub mod instantiate;
pub mod migration;
pub mod query;
pub mod sudo;
pub mod utils;
28 changes: 28 additions & 0 deletions contracts/emissions_controller/src/migration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#![cfg(not(tarpaulin_include))]

use cosmwasm_std::{entry_point, DepsMut, Empty, Env, Response};
use cw2::{get_contract_version, set_contract_version};

use crate::error::ContractError;
use crate::instantiate::{CONTRACT_NAME, CONTRACT_VERSION};

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn migrate(deps: DepsMut, _env: Env, _msg: Empty) -> Result<Response, ContractError> {
let contract_version = get_contract_version(deps.storage)?;

match contract_version.contract.as_ref() {
CONTRACT_NAME => match contract_version.version.as_ref() {
"1.0.0" => Ok(()),
_ => Err(ContractError::MigrationError {}),
},
_ => Err(ContractError::MigrationError {}),
}?;

set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

Ok(Response::new()
.add_attribute("previous_contract_name", &contract_version.contract)
.add_attribute("previous_contract_version", &contract_version.version)
.add_attribute("new_contract_name", CONTRACT_NAME)
.add_attribute("new_contract_version", CONTRACT_VERSION))
}
31 changes: 31 additions & 0 deletions contracts/emissions_controller/tests/common/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,30 @@ impl ControllerHelper {
)
}

pub fn instant_unlock(&mut self, user: &Addr, amount: u128) -> AnyResult<AppResponse> {
self.app.execute_contract(
user.clone(),
self.vxastro.clone(),
&voting_escrow::ExecuteMsg::InstantUnlock {
amount: amount.into(),
},
&[],
)
}

pub fn set_privileged_list(
&mut self,
sender: &Addr,
list: Vec<String>,
) -> AnyResult<AppResponse> {
self.app.execute_contract(
sender.clone(),
self.vxastro.clone(),
&voting_escrow::ExecuteMsg::SetPrivilegedList { list },
&[],
)
}

pub fn relock(&mut self, user: &Addr) -> AnyResult<AppResponse> {
self.app.execute_contract(
user.clone(),
Expand Down Expand Up @@ -411,6 +435,13 @@ impl ControllerHelper {
)
}

pub fn total_vp(&self, timestamp: Option<u64>) -> StdResult<Uint128> {
self.app.wrap().query_wasm_smart(
&self.vxastro,
&voting_escrow::QueryMsg::TotalVotingPower { timestamp },
)
}

pub fn user_info(&self, user: &Addr, timestamp: Option<u64>) -> StdResult<UserInfoResponse> {
self.app.wrap().query_wasm_smart(
&self.emission_controller,
Expand Down
Loading
Loading