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(em. controller): add blacklisting logic #118

Merged
merged 3 commits into from
Nov 6, 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
12 changes: 6 additions & 6 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions 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.1.2"
version = "1.2.0"
authors = ["Astroport"]
edition = "2021"
description = "Astroport vxASTRO Emissions Voting Contract"
Expand All @@ -23,7 +23,7 @@ cw-storage-plus.workspace = true
cosmwasm-schema.workspace = true
thiserror.workspace = true
itertools.workspace = true
astroport-governance = { path = "../../packages/astroport-governance", version = "4.2" }
astroport-governance = { path = "../../packages/astroport-governance", version = "4.3" }
astroport.workspace = true
neutron-sdk = "0.10.0"
serde_json = "1"
Expand Down
3 changes: 3 additions & 0 deletions contracts/emissions_controller/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,7 @@ pub enum ContractError {

#[error("Outpost {prefix} is jailed. Only vxASTRO unlocks are available")]
JailedOutpost { prefix: String },

#[error("Pool {0} is blacklisted")]
PoolIsBlacklisted(String),
}
76 changes: 71 additions & 5 deletions contracts/emissions_controller/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ use astroport::incentives;
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{
attr, ensure, to_json_binary, wasm_execute, BankMsg, Coin, CosmosMsg, Decimal, DepsMut, Env,
Fraction, IbcMsg, IbcTimeout, MessageInfo, Order, Response, StdError, StdResult, Storage,
Uint128,
attr, ensure, ensure_eq, to_json_binary, wasm_execute, BankMsg, Coin, CosmosMsg, Decimal,
DepsMut, Env, Fraction, IbcMsg, IbcTimeout, MessageInfo, Order, Response, StdError, StdResult,
Storage, Uint128,
};
use cw_utils::{must_pay, nonpayable};
use itertools::Itertools;
Expand All @@ -29,8 +29,8 @@ use astroport_governance::{assembly, voting_escrow};

use crate::error::ContractError;
use crate::state::{
get_active_outposts, CONFIG, OUTPOSTS, OWNERSHIP_PROPOSAL, POOLS_WHITELIST, TUNE_INFO,
USER_INFO, VOTED_POOLS,
get_active_outposts, CONFIG, OUTPOSTS, OWNERSHIP_PROPOSAL, POOLS_BLACKLIST, POOLS_WHITELIST,
TUNE_INFO, USER_INFO, VOTED_POOLS,
};
use crate::utils::{
build_emission_ibc_msg, get_epoch_start, get_outpost_prefix, jail_outpost, min_ntrn_ibc_fee,
Expand Down Expand Up @@ -136,6 +136,9 @@ pub fn execute(
}
ExecuteMsg::Custom(hub_msg) => match hub_msg {
HubMsg::WhitelistPool { lp_token: pool } => whitelist_pool(deps, env, info, pool),
HubMsg::UpdateBlacklist { add, remove } => {
update_blacklist(deps, info, env, add, remove)
}
HubMsg::UpdateOutpost {
prefix,
astro_denom,
Expand Down Expand Up @@ -191,6 +194,12 @@ pub fn whitelist_pool(
ContractError::IncorrectWhitelistFee(config.whitelisting_fee)
);

// Ensure that LP token is not blacklisted
ensure!(
!POOLS_BLACKLIST.has(deps.storage, &pool),
ContractError::PoolIsBlacklisted(pool.clone())
);

// Perform basic LP token validation. Ensure the outpost exists.
let outposts = get_active_outposts(deps.storage)?;
if let Some(prefix) = get_outpost_prefix(&pool, &outposts) {
Expand Down Expand Up @@ -244,6 +253,63 @@ pub fn whitelist_pool(
.add_attributes([attr("action", "whitelist_pool"), attr("pool", &pool)]))
}

pub fn update_blacklist(
deps: DepsMut<NeutronQuery>,
info: MessageInfo,
env: Env,
add: Vec<String>,
remove: Vec<String>,
) -> Result<Response<NeutronMsg>, ContractError> {
let config = CONFIG.load(deps.storage)?;

ensure_eq!(info.sender, config.owner, ContractError::Unauthorized {});

// Checking for duplicates
ensure!(
remove.iter().chain(add.iter()).all_unique(),
StdError::generic_err("Duplicated LP tokens found")
);

// Remove pools from blacklist
for lp_token in &remove {
ensure!(
POOLS_BLACKLIST.has(deps.storage, lp_token),
StdError::generic_err(format!("LP token {lp_token} wasn't found in the blacklist"))
);

POOLS_BLACKLIST.remove(deps.storage, lp_token);
}

// Add pools to blacklist
for lp_token in &add {
ensure!(
!POOLS_BLACKLIST.has(deps.storage, lp_token),
StdError::generic_err(format!("LP token {lp_token} is already blacklisted"))
);

// If key doesn't exist .remove() doesn't throw an error
VOTED_POOLS.remove(deps.storage, lp_token, env.block.time.seconds())?;
POOLS_BLACKLIST.save(deps.storage, lp_token, &())?;
}

// And remove pools from the whitelist if they are there
POOLS_WHITELIST.update::<_, StdError>(deps.storage, |mut whitelist| {
whitelist.retain(|pool| !add.contains(pool));
Ok(whitelist)
})?;

let mut attrs = vec![attr("action", "update_blacklist")];

if !add.is_empty() {
attrs.push(attr("add", add.into_iter().join(",")));
}
if !remove.is_empty() {
attrs.push(attr("remove", remove.into_iter().join(",")));
}

Ok(Response::default().add_attributes(attrs))
}

/// Permissioned endpoint to add or update outpost.
/// Performs several simple checks to cut off possible human errors.
pub fn update_outpost(
Expand Down
14 changes: 12 additions & 2 deletions contracts/emissions_controller/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use astroport_governance::emissions_controller::hub::{

use crate::error::ContractError;
use crate::state::{
get_active_outposts, get_all_outposts, CONFIG, POOLS_WHITELIST, TUNE_INFO, USER_INFO,
VOTED_POOLS,
get_active_outposts, get_all_outposts, CONFIG, POOLS_BLACKLIST, POOLS_WHITELIST, TUNE_INFO,
USER_INFO, VOTED_POOLS,
};
use crate::utils::simulate_tune;

Expand Down Expand Up @@ -122,6 +122,16 @@ pub fn query(deps: Deps<NeutronQuery>, env: Env, msg: QueryMsg) -> Result<Binary

Ok(to_json_binary(pools_whitelist)?)
}
QueryMsg::QueryBlacklist { limit, start_after } => {
let limit = limit.unwrap_or(MAX_PAGE_LIMIT) as usize;
let start_after = start_after.as_ref().map(|s| Bound::exclusive(s.as_str()));
let pools_blacklist = POOLS_BLACKLIST
.keys(deps.storage, start_after, None, Order::Ascending)
.take(limit)
.collect::<StdResult<Vec<_>>>()?;

Ok(to_json_binary(&pools_blacklist)?)
}
QueryMsg::CheckWhitelist { lp_tokens } => {
let whitelist = POOLS_WHITELIST.load(deps.storage)?;
let is_whitelisted = lp_tokens
Expand Down
1 change: 1 addition & 0 deletions contracts/emissions_controller/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub const CONFIG: Item<Config> = Item::new("config");
pub const OWNERSHIP_PROPOSAL: Item<OwnershipProposal> = Item::new("ownership_proposal");
/// Array of pools eligible for voting.
pub const POOLS_WHITELIST: Item<Vec<String>> = Item::new("pools_whitelist");
pub const POOLS_BLACKLIST: Map<&str, ()> = Map::new("pools_blacklist");
/// Registered Astroport outposts with respective parameters.
pub const OUTPOSTS: Map<&str, OutpostInfo> = Map::new("outposts");
/// Historical user's voting information.
Expand Down
24 changes: 24 additions & 0 deletions contracts/emissions_controller/tests/common/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,20 @@ impl ControllerHelper {
)
}

pub fn update_blacklist(
&mut self,
user: &Addr,
add: Vec<String>,
remove: Vec<String>,
) -> AnyResult<AppResponse> {
self.app.execute_contract(
user.clone(),
self.emission_controller.clone(),
&emissions_controller::msg::ExecuteMsg::Custom(HubMsg::UpdateBlacklist { add, remove }),
&[],
)
}

pub fn add_outpost(&mut self, prefix: &str, outpost: OutpostInfo) -> AnyResult<AppResponse> {
self.app.execute_contract(
self.owner.clone(),
Expand Down Expand Up @@ -573,6 +587,16 @@ impl ControllerHelper {
)
}

pub fn query_blacklist(&self) -> StdResult<Vec<String>> {
self.app.wrap().query_wasm_smart(
&self.emission_controller,
&emissions_controller::hub::QueryMsg::QueryBlacklist {
limit: Some(100),
start_after: None,
},
)
}

pub fn check_whitelist(&self, lp_tokens: Vec<String>) -> StdResult<Vec<(String, bool)>> {
self.app.wrap().query_wasm_smart(
&self.emission_controller,
Expand Down
Loading
Loading