Skip to content

Commit

Permalink
funding(lqt): forbid null power votes
Browse files Browse the repository at this point in the history
  • Loading branch information
erwanor committed Feb 6, 2025
1 parent 3a44f29 commit 5552ba6
Showing 1 changed file with 17 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use anyhow::{anyhow, ensure, Context as _};
use async_trait::async_trait;
use cnidarium::{StateRead, StateWrite};
use cnidarium::StateWrite;
use cnidarium_component::ActionHandler;
use penumbra_sdk_asset::{asset::Denom, Value};
use penumbra_sdk_asset::asset::Denom;
use penumbra_sdk_governance::StateReadExt as _;
use penumbra_sdk_num::Amount;
use penumbra_sdk_proof_params::DELEGATOR_VOTE_PROOF_VERIFICATION_KEY;
use penumbra_sdk_sct::component::{clock::EpochRead as _, source::SourceContext as _};
use penumbra_sdk_sct::epoch::Epoch;
use penumbra_sdk_stake::component::validator_handler::ValidatorDataRead as _;
use penumbra_sdk_stake::validator::State;
use penumbra_sdk_tct::Position;
use penumbra_sdk_txhash::TransactionContext;

Expand Down Expand Up @@ -45,20 +46,6 @@ async fn start_position_good_for_epoch(epoch: Epoch, start: Position) -> anyhow:
Ok(())
}

/// Fetch the unbonded equivalent of some purported delegation token.
///
/// Will fail if (either):
/// - the token is not for a known validator,
/// - the validator does not have any rate data.
async fn unbonded_amount(state: impl StateRead, value: Value) -> anyhow::Result<Amount> {
let validator = state.validator_by_delegation_asset(value.asset_id).await?;
let rate = state
.get_validator_rate(&validator)
.await?
.ok_or_else(|| anyhow!("{} has no rate data", &validator))?;
Ok(rate.unbonded_amount(value.amount))
}

// This isolates the logic for how we should handle out of bounds amounts.
fn voting_power(amount: Amount) -> u64 {
amount
Expand Down Expand Up @@ -143,15 +130,26 @@ impl ActionHandler for ActionLiquidityTournamentVote {
anyhow::bail!("validator {} is unknown", validator)
};

use penumbra_sdk_stake::validator::State;
ensure!(
!matches!(validator_state, State::Defined | State::Tombstoned),
"validator {} is not in a valid state (Defined or Tombstoned)",
validator
);

// 5. Ok, actually tally.
let power = voting_power(unbonded_amount(&state, self.body.value).await?);
// 5. Check that the validator rate exists and that the unbonded amount is non-zero.
let validator_rate = state
.get_validator_rate(&validator)
.await?
.ok_or_else(|| anyhow!("{} has no rate data", validator))?;
let unbonded_amount = validator_rate.unbonded_amount(self.body.value.amount);

ensure!(
unbonded_amount > Amount::zero(),
"unbonded amount of delegation token is zero"
);

// 6. Ok, actually tally.
let power = voting_power(unbonded_amount);
let incentivized = self
.body
.incentivized_id()
Expand Down

0 comments on commit 5552ba6

Please sign in to comment.