defios 0.1.0

Main github on-chain integrations by DefiOS
Documentation
use crate::constants::VOTING_END;
use crate::error::DefiOSError;
use crate::event::ObjectiveProposalVoted;
use crate::state::{Grantee, Objective, ObjectiveProposal, ObjectiveProposalVote};
use anchor_lang::prelude::*;

#[derive(Accounts)]
pub struct VoteObjective<'info> {
    #[account(mut)]
    pub voter: Signer<'info>,
    #[account(
        constraint = objective.completed_at == None
    )]
    pub objective: Account<'info, Objective>,
    #[account(
        mut,
        seeds = [
            voter.key().as_ref(),
            objective.objective_repository.as_ref(),
            grant_account.objective.as_ref(),
        ],
        bump = grant_account.bump
    )]
    pub grant_account: Account<'info, Grantee>,
    #[account(
        mut,
        seeds = [
            b"objective_proposal",
            objective.key().as_ref(),
            proposal.proposal_id.as_bytes()
        ],
        bump = proposal.bump
    )]
    pub proposal: Account<'info, ObjectiveProposal>,
    #[account(
        init_if_needed,
        payer = voter,
        seeds = [
            proposal.key().as_ref(),
            objective.key().as_ref(),
            voter.key().as_ref()
        ],
        space = 8+ ObjectiveProposalVote::INIT_SPACE,
        bump
    )]
    pub objective_proposal_vote: Account<'info, ObjectiveProposalVote>,
    pub system_program: Program<'info, System>,
}

pub fn handler(ctx: Context<VoteObjective>, positive: bool) -> Result<()> {
    let voter = &ctx.accounts.voter;
    let grant_account = &mut ctx.accounts.grant_account;
    let proposal = &mut ctx.accounts.proposal;
    let objective = &ctx.accounts.objective;
    let objective_proposal_vote = &mut ctx.accounts.objective_proposal_vote;

    let current_time = Clock::get()?.unix_timestamp;
    require!(
        current_time - proposal.proposed_at <= VOTING_END,
        DefiOSError::VotingPeriodEnded
    );

    let capacity = grant_account.staked_amount - objective_proposal_vote.voted_amount;
    let mut vote_side = positive;
    if objective_proposal_vote.voted_amount == 0 {
        objective_proposal_vote.state = positive;
    } else {
        vote_side = objective_proposal_vote.state;
    };

    if vote_side {
        proposal.vote_amount += capacity;
    } else {
        proposal.deny_amount += capacity;
    };

    objective_proposal_vote.voted_amount += capacity;

    emit!(ObjectiveProposalVoted {
        voter: voter.key(),
        objective: objective.key(),
        objective_proposal: proposal.key(),
        vote_amount: grant_account.staked_amount,
    });

    Ok(())
}