Skip to content

Commit

Permalink
fix(vxASTRO): using total locked xASTRO as governance voting power
Browse files Browse the repository at this point in the history
  • Loading branch information
epanchee committed Dec 9, 2024
1 parent 0795721 commit 1d0c4f4
Show file tree
Hide file tree
Showing 23 changed files with 179 additions and 37 deletions.
16 changes: 8 additions & 8 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion contracts/assembly/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "astro-assembly"
version = "3.0.0"
version = "3.0.1"
authors = ["Astroport"]
edition = "2021"
description = "Astroport DAO Contract"
Expand Down
1 change: 1 addition & 0 deletions contracts/assembly/src/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: Empty) -> Result<Response, Contra
.map_err(ContractError::Std)
})
}
"3.0.0" => Ok(()),
_ => Err(ContractError::MigrationError {}),
},
_ => Err(ContractError::MigrationError {}),
Expand Down
17 changes: 10 additions & 7 deletions contracts/assembly/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use astroport_governance::builder_unlock::{
AllocationResponse, QueryMsg as BuilderUnlockQueryMsg, State,
};
use astroport_governance::voting_escrow;
use astroport_governance::voting_escrow::LockInfoResponse;

use crate::state::CONFIG;

Expand Down Expand Up @@ -36,13 +37,15 @@ pub fn calc_voting_power(deps: Deps, sender: String, proposal: &Proposal) -> Std
)?;

let vxastro_vp = if let Some(vxastro_contract) = &config.vxastro_contract {
deps.querier.query_wasm_smart(
vxastro_contract,
&voting_escrow::QueryMsg::UserVotingPower {
user: sender,
timestamp: Some(proposal.start_time - 1),
},
)?
deps.querier
.query_wasm_smart(
vxastro_contract,
&voting_escrow::QueryMsg::LockInfo {
user: sender,
timestamp: Some(proposal.start_time - 1),
},
)
.map(|resp: LockInfoResponse| resp.amount)?
} else {
Uint128::zero()
};
Expand Down
16 changes: 13 additions & 3 deletions contracts/assembly/tests/assembly_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,10 @@ fn test_voting_power() {
})
.collect();

let test_user = Addr::unchecked("test_user");
let test_user_vp = 100_000000u128;
helper.get_vxastro(&test_user, test_user_vp);

let submitter = balances.iter().last().unwrap().0;
helper.get_xastro(submitter, PROPOSAL_REQUIRED_DEPOSIT.u128());
total_xastro += PROPOSAL_REQUIRED_DEPOSIT.u128();
Expand All @@ -761,9 +765,15 @@ fn test_voting_power() {
let proposal = helper.proposal(1);
assert_eq!(
proposal.total_voting_power.u128(),
total_xastro + total_builder_allocation + total_vxastro + 1001
total_xastro + total_builder_allocation + total_vxastro + 1001 + test_user_vp
);

// test_user starts vxASTRO unlocking, but his governance voting power must not change
helper.unlock_vxastro(&test_user).unwrap();
assert_eq!(helper.user_vp(&test_user, 1).u128(), 100_000000);
// However, his VP in emissions voting has been nullified
assert_eq!(helper.vxastro_vp(&test_user, None).unwrap().u128(), 0);

// First 40 users vote against the proposal
let mut against_power = 0u128;
balances.iter().take(40).for_each(|(addr, balances)| {
Expand Down Expand Up @@ -796,7 +806,7 @@ fn test_voting_power() {
let proposal = helper.proposal(1);
assert_eq!(
proposal.total_voting_power.u128(),
total_xastro + total_builder_allocation + total_vxastro + 1001
total_xastro + total_builder_allocation + total_vxastro + 1001 + 100_000000u128
);

helper.next_block_height(PROPOSAL_VOTING_PERIOD);
Expand All @@ -807,7 +817,7 @@ fn test_voting_power() {

assert_eq!(
proposal.total_voting_power.u128(),
total_xastro + total_builder_allocation + total_vxastro + 1001
total_xastro + total_builder_allocation + total_vxastro + 1001 + 100_000000u128
);
assert_eq!(proposal.submitter, submitter.clone());
assert_eq!(proposal.status, ProposalStatus::Passed);
Expand Down
19 changes: 19 additions & 0 deletions contracts/assembly/tests/common/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,16 @@ impl Helper {
.unwrap()
}

pub fn vxastro_vp(&self, user: &Addr, timestamp: Option<u64>) -> StdResult<Uint128> {
self.app.wrap().query_wasm_smart(
&self.vxastro,
&voting_escrow::QueryMsg::UserVotingPower {
user: user.to_string(),
timestamp,
},
)
}

pub fn proposal(&self, proposal_id: u64) -> Proposal {
self.app
.wrap()
Expand Down Expand Up @@ -554,4 +564,13 @@ impl Helper {
block.height += height
});
}

pub fn unlock_vxastro(&mut self, user: &Addr) -> AnyResult<AppResponse> {
self.app.execute_contract(
user.clone(),
self.vxastro.clone(),
&voting_escrow::ExecuteMsg::Unlock {},
&[],
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1491,6 +1491,7 @@ fn test_instant_unlock_vxastro() {
&helper.vxastro,
&voting_escrow::QueryMsg::LockInfo {
user: alice.to_string(),
timestamp: None,
},
)
.unwrap();
Expand Down
2 changes: 1 addition & 1 deletion contracts/emissions_controller_outpost/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "astroport-emissions-controller-outpost"
version = "1.1.0"
version = "1.2.0"
authors = ["Astroport"]
edition = "2021"
description = "Astroport vxASTRO Emissions Voting Contract. Outpost version"
Expand Down
14 changes: 12 additions & 2 deletions contracts/emissions_controller_outpost/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ use astroport_governance::emissions_controller::utils::{
check_lp_token, get_total_voting_power, get_voting_power,
};
use astroport_governance::utils::check_contract_supports_channel;
use astroport_governance::voting_escrow;
use astroport_governance::voting_escrow::LockInfoResponse;

use crate::error::ContractError;
use crate::state::{CONFIG, OWNERSHIP_PROPOSAL, PROPOSAL_VOTERS, REGISTERED_PROPOSALS};
Expand Down Expand Up @@ -391,8 +393,16 @@ pub fn governance_vote(

let start_time = REGISTERED_PROPOSALS.load(deps.storage, proposal_id)?;

let voting_power =
get_voting_power(deps.querier, &config.vxastro, &voter, Some(start_time - 1))?;
let voting_power = deps
.querier
.query_wasm_smart(
&config.vxastro,
&voting_escrow::QueryMsg::LockInfo {
user: voter.clone(),
timestamp: Some(start_time - 1),
},
)
.map(|resp: LockInfoResponse| resp.amount)?;
ensure!(!voting_power.is_zero(), ContractError::ZeroVotingPower {});

let total_voting_power =
Expand Down
1 change: 1 addition & 0 deletions contracts/emissions_controller_outpost/src/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: Empty) -> Result<Response, Contra
match contract_version.contract.as_ref() {
CONTRACT_NAME => match contract_version.version.as_ref() {
"1.0.0" => Ok(()),
"1.1.0" => Ok(()),
_ => Err(ContractError::MigrationError {}),
},
_ => Err(ContractError::MigrationError {}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,11 +353,12 @@ impl ControllerHelper {
.map(|x| x.rewards)
}

pub fn lock_info(&self, user: &Addr) -> StdResult<LockInfoResponse> {
pub fn lock_info(&self, user: &Addr, timestamp: Option<u64>) -> StdResult<LockInfoResponse> {
self.app.wrap().query_wasm_smart(
&self.vxastro,
&voting_escrow::QueryMsg::LockInfo {
user: user.to_string(),
timestamp,
},
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use astroport_emissions_controller_outpost::error::ContractError;
use astroport_governance::assembly::ProposalVoteOption;
use astroport_governance::emissions_controller::consts::{EPOCH_LENGTH, IBC_TIMEOUT};
use astroport_governance::emissions_controller::msg::{ExecuteMsg, VxAstroIbcMsg};
use astroport_governance::emissions_controller::outpost::UserIbcError;
use astroport_governance::emissions_controller::outpost::{UserIbcError, UserIbcStatus};
use astroport_governance::voting_escrow::LockInfoResponse;
use astroport_governance::{emissions_controller, voting_escrow};
use astroport_voting_escrow::state::UNLOCK_PERIOD;
Expand Down Expand Up @@ -463,7 +463,7 @@ fn test_voting() {
err: "error".to_string()
})
);
let lock_info = helper.lock_info(&user).unwrap();
let lock_info = helper.lock_info(&user, None).unwrap();
assert_eq!(
lock_info,
LockInfoResponse {
Expand Down Expand Up @@ -721,6 +721,60 @@ fn test_interchain_governance() {
)
.unwrap();
assert_eq!(voters, vec![user.to_string()]);

// Confirm that unlocking user can vote on proposals

helper.unlock(&user).unwrap();
helper.timetravel(1000);
let now = helper.app.block_info().time.seconds();

helper
.mock_packet_receive(
VxAstroIbcMsg::RegisterProposal {
proposal_id: 3,
start_time: now,
},
"channel-1",
)
.unwrap();

// Mock ibc ack
helper
.mock_ibc_ack(
VxAstroIbcMsg::UpdateUserVotes {
voter: user.to_string(),
voting_power: Default::default(),
total_voting_power: Default::default(),
is_unlock: false,
},
None,
)
.unwrap();

helper.cast_vote(&user, 3).unwrap();

// Confirm that valid voting power has been used
assert_eq!(
helper.query_ibc_status(&user).unwrap(),
UserIbcStatus {
pending_msg: Some(VxAstroIbcMsg::GovernanceVote {
voter: user.to_string(),
voting_power: 1000u128.into(),
// Note!
// Even this looks counterintuitive, this field is exclusively used to prevent
// possible malicious activity like infinite IBC tokens minting.
// Anyway,
// attacker must get voting power via locking vxASTRO and waiting Hub confirmation.
// At this stage, Hub will jail this outpost and stop receiving any messages except unlocking.
// So,
// it is totally safe to allow here discrepancy between voting power and total voting power.
total_voting_power: 0u128.into(),
proposal_id: 3,
vote: ProposalVoteOption::For,
}),
error: None
}
)
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion contracts/voting_escrow/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "astroport-voting-escrow"
version = "1.1.0"
version = "1.2.0"
authors = ["Astroport"]
edition = "2021"
description = "Astroport Vote Escrowed xASTRO (vxASTRO)"
Expand Down
4 changes: 2 additions & 2 deletions contracts/voting_escrow/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,10 +285,10 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
QueryMsg::UserVotingPower { user, timestamp } => {
to_json_binary(&query_user_voting_power(deps, env, user, timestamp)?)
}
QueryMsg::LockInfo { user } => {
QueryMsg::LockInfo { user, timestamp } => {
let user = deps.api.addr_validate(&user)?;
let lock_info_resp: LockInfoResponse =
Lock::load(deps.storage, env.block.time.seconds(), &user)?.into();
Lock::load_at_ts(deps.storage, env.block.time.seconds(), &user, timestamp)?.into();
to_json_binary(&lock_info_resp)
}
QueryMsg::Config {} => to_json_binary(&CONFIG.load(deps.storage)?),
Expand Down
1 change: 1 addition & 0 deletions contracts/voting_escrow/src/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: Empty) -> Result<Response, Contra
match contract_version.contract.as_ref() {
CONTRACT_NAME => match contract_version.version.as_ref() {
"1.0.0" => Ok(()),
"1.1.0" => Ok(()),
_ => Err(ContractError::MigrationError {}),
},
_ => Err(ContractError::MigrationError {}),
Expand Down
3 changes: 2 additions & 1 deletion contracts/voting_escrow/tests/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,12 @@ impl EscrowHelper {
)
}

pub fn lock_info(&self, user: &Addr) -> StdResult<LockInfoResponse> {
pub fn lock_info(&self, user: &Addr, timestamp: Option<u64>) -> StdResult<LockInfoResponse> {
self.app.wrap().query_wasm_smart(
&self.vxastro_contract,
&QueryMsg::LockInfo {
user: user.to_string(),
timestamp,
},
)
}
Expand Down
Loading

0 comments on commit 1d0c4f4

Please sign in to comment.