gauge/instructions/
gauge_set_vote.rs

1//! Votes for a [Gauge].
2
3use crate::*;
4
5/// Accounts for [gauge::gauge_set_vote].
6#[derive(Accounts)]
7pub struct GaugeSetVote<'info> {
8    /// The [Gaugemeister].
9    pub gaugemeister: Account<'info, Gaugemeister>,
10    /// The [Gauge].
11    pub gauge: Account<'info, Gauge>,
12
13    /// The [GaugeVoter].
14    #[account(mut)]
15    pub gauge_voter: Account<'info, GaugeVoter>,
16    /// The [GaugeVote].
17    #[account(mut)]
18    pub gauge_vote: Account<'info, GaugeVote>,
19
20    /// The escrow.
21    #[account(has_one = vote_delegate @ crate::ErrorCode::UnauthorizedNotDelegate)]
22    pub escrow: Account<'info, locked_voter::Escrow>,
23
24    /// The vote delegate.
25    pub vote_delegate: Signer<'info>,
26}
27
28impl<'info> GaugeSetVote<'info> {
29    fn next_total_weight(&self, new_weight: u32) -> Option<u32> {
30        let total_weight = self
31            .gauge_voter
32            .total_weight
33            .checked_sub(self.gauge_vote.weight)?
34            .checked_add(new_weight)?;
35        Some(total_weight)
36    }
37
38    /// Sets a non-zero vote.
39    fn set_vote(&mut self, weight: u32) -> Result<()> {
40        if weight != 0 {
41            invariant!(!self.gauge.is_disabled, CannotVoteGaugeDisabled);
42        }
43
44        if self.gauge_vote.weight == weight {
45            // Don't do anything if the weight is not changed.
46            return Ok(());
47        }
48
49        let next_total_weight = unwrap_int!(self.next_total_weight(weight));
50
51        let voter = &mut self.gauge_voter;
52        let vote = &mut self.gauge_vote;
53
54        // update voter
55        let prev_total_weight = voter.total_weight;
56        voter.total_weight = next_total_weight;
57
58        // record that the weights have changed.
59        voter.weight_change_seqno = unwrap_int!(voter.weight_change_seqno.checked_add(1));
60
61        // update vote
62        vote.weight = weight;
63
64        emit!(SetGaugeVoteEvent {
65            gaugemeister: self.gaugemeister.key(),
66            gauge: self.gauge.key(),
67            quarry: self.gauge.quarry,
68            gauge_voter_owner: voter.owner,
69            vote_delegate: self.vote_delegate.key(),
70            prev_total_weight,
71            total_weight: voter.total_weight,
72            weight_change_seqno: voter.weight_change_seqno,
73        });
74
75        Ok(())
76    }
77}
78
79pub fn handler(ctx: Context<GaugeSetVote>, weight: u32) -> Result<()> {
80    ctx.accounts.set_vote(weight)
81}
82
83impl<'info> Validate<'info> for GaugeSetVote<'info> {
84    fn validate(&self) -> Result<()> {
85        assert_keys_eq!(self.gaugemeister, self.gauge.gaugemeister);
86        assert_keys_eq!(self.gauge, self.gauge_vote.gauge);
87        assert_keys_eq!(self.gauge_voter, self.gauge_vote.gauge_voter);
88
89        assert_keys_eq!(self.escrow, self.gauge_voter.escrow);
90        assert_keys_eq!(self.vote_delegate, self.escrow.vote_delegate);
91        Ok(())
92    }
93}
94
95/// Event called in [gauge::gauge_set_vote].
96#[event]
97pub struct SetGaugeVoteEvent {
98    #[index]
99    /// The [Gaugemeister].
100    pub gaugemeister: Pubkey,
101    #[index]
102    /// The [Gauge].
103    pub gauge: Pubkey,
104    #[index]
105    /// The [quarry_mine::Quarry] being voted on.
106    pub quarry: Pubkey,
107    #[index]
108    /// Owner of the Escrow of the [GaugeVoter].
109    pub gauge_voter_owner: Pubkey,
110    #[index]
111    pub vote_delegate: Pubkey,
112    pub prev_total_weight: u32,
113    pub total_weight: u32,
114    pub weight_change_seqno: u64,
115}