voter-stake-registry/programs/voter-stake-registry/src/instructions/clawback.rs

56 lines
1.8 KiB
Rust

use crate::error::*;
use crate::state::lockup::*;
use crate::state::registrar::registrar_seeds;
use anchor_lang::prelude::*;
use anchor_spl::token;
use super::withdraw::WithdrawOrClawback;
pub fn clawback(ctx: Context<WithdrawOrClawback>, deposit_id: u8) -> Result<()> {
msg!("--------clawback--------");
// Load the accounts.
let registrar = &ctx.accounts.registrar;
let voter = &mut ctx.accounts.voter.load_mut()?;
require!(voter.deposits.len() > deposit_id.into(), InvalidDepositId);
require!(
ctx.accounts.authority.key() == registrar.clawback_authority,
InvalidAuthority
);
// Get the deposit being withdrawn from.
let curr_ts = registrar.clock_unix_timestamp();
let deposit_entry = &mut voter.deposits[deposit_id as usize];
require!(deposit_entry.is_used, InvalidDepositId);
require!(
deposit_entry.allow_clawback,
ErrorCode::ClawbackNotAllowedOnDeposit
);
let unvested_amount =
deposit_entry.amount_initially_locked_native - deposit_entry.vested(curr_ts).unwrap();
// sanity check only
require!(
deposit_entry.amount_deposited_native >= unvested_amount,
InsufficientVestedTokens
);
// Transfer the tokens to withdraw.
let registrar_seeds = registrar_seeds!(registrar);
token::transfer(
ctx.accounts.transfer_ctx().with_signer(&[registrar_seeds]),
unvested_amount,
)?;
// Update deposit book keeping.
deposit_entry.amount_deposited_native -= unvested_amount;
// Now that all locked funds are withdrawn, end the lockup
deposit_entry.amount_initially_locked_native = 0;
deposit_entry.lockup.kind = LockupKind::None;
deposit_entry.lockup.start_ts = registrar.clock_unix_timestamp();
deposit_entry.lockup.end_ts = deposit_entry.lockup.start_ts;
deposit_entry.allow_clawback = false;
Ok(())
}