Add instruction for closing deposits
This commit is contained in:
parent
d529dab2d6
commit
2c608ebe46
|
@ -262,10 +262,17 @@ impl<'info> Withdraw<'info> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct CloseDeposit<'info> {
|
||||
#[account(mut, has_one = authority)]
|
||||
pub voter: AccountLoader<'info, Voter>,
|
||||
pub authority: Signer<'info>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct UpdateSchedule<'info> {
|
||||
pub registrar: AccountLoader<'info, Registrar>,
|
||||
#[account(mut, has_one = authority)]
|
||||
#[account(mut, has_one = authority, has_one = registrar)]
|
||||
pub voter: AccountLoader<'info, Voter>,
|
||||
pub authority: Signer<'info>,
|
||||
}
|
||||
|
|
|
@ -217,6 +217,7 @@ pub mod governance_registry {
|
|||
|
||||
require!(voter.deposits.len() > id as usize, InvalidDepositId);
|
||||
let d_entry = &mut voter.deposits[id as usize];
|
||||
require!(d_entry.is_used, InvalidDepositId);
|
||||
|
||||
// Deposit tokens into the registrar.
|
||||
token::transfer(ctx.accounts.transfer_ctx(), amount)?;
|
||||
|
@ -359,6 +360,22 @@ pub mod governance_registry {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Close an empty deposit, allowing it to be reused in the future
|
||||
pub fn close_deposit(ctx: Context<CloseDeposit>, deposit_id: u8) -> Result<()> {
|
||||
let voter = &mut ctx.accounts.voter.load_mut()?;
|
||||
|
||||
require!(voter.deposits.len() > deposit_id as usize, InvalidDepositId);
|
||||
let d = &mut voter.deposits[deposit_id as usize];
|
||||
require!(d.is_used, InvalidDepositId);
|
||||
require!(d.amount_deposited_native == 0, VotingTokenNonZero);
|
||||
|
||||
// We do not need to check d.amount_initially_locked_native or d.lockup
|
||||
// here - the fact that the deposit contains no tokens is sufficient.
|
||||
|
||||
d.is_used = false;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Resets a lockup to start at the current slot timestamp and to last for
|
||||
/// `periods`, which must be >= the number of periods left on the lockup.
|
||||
/// This will re-lock any non-withdrawn vested funds.
|
||||
|
|
|
@ -410,6 +410,38 @@ impl AddinCookie {
|
|||
.await)
|
||||
}
|
||||
|
||||
pub async fn close_deposit(
|
||||
&self,
|
||||
voter: &VoterCookie,
|
||||
authority: &Keypair,
|
||||
deposit_id: u8,
|
||||
) -> Result<(), TransportError> {
|
||||
let data = anchor_lang::InstructionData::data(
|
||||
&governance_registry::instruction::CloseDeposit { deposit_id },
|
||||
);
|
||||
|
||||
let accounts = anchor_lang::ToAccountMetas::to_account_metas(
|
||||
&governance_registry::accounts::CloseDeposit {
|
||||
voter: voter.address,
|
||||
authority: authority.pubkey(),
|
||||
},
|
||||
None,
|
||||
);
|
||||
|
||||
let instructions = vec![Instruction {
|
||||
program_id: self.program_id,
|
||||
accounts,
|
||||
data,
|
||||
}];
|
||||
|
||||
// clone the secrets
|
||||
let signer = Keypair::from_base58_string(&authority.to_base58_string());
|
||||
|
||||
self.solana
|
||||
.process_transaction(&instructions, Some(&[&signer]))
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn set_time_offset(
|
||||
&self,
|
||||
registrar: &RegistrarCookie,
|
||||
|
|
|
@ -226,5 +226,7 @@ async fn test_deposit_daily_vesting() -> Result<(), TransportError> {
|
|||
assert_eq!(after_withdraw.vault, 0);
|
||||
assert_eq!(after_withdraw.deposit, 0);
|
||||
|
||||
addin.close_deposit(&voter, &voter_authority, 0).await.unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -227,6 +227,9 @@ async fn test_deposit_monthly_vesting() -> Result<(), TransportError> {
|
|||
assert_eq!(after_deposit.vault, 1000);
|
||||
assert_eq!(after_deposit.deposit, 1000);
|
||||
|
||||
// cannot close yet, has funds
|
||||
addin.close_deposit(&voter, &voter_authority, 0).await.expect_err("deposit not empty");
|
||||
|
||||
withdraw(1000).await.unwrap();
|
||||
|
||||
let after_withdraw = get_balances(0).await;
|
||||
|
@ -235,5 +238,7 @@ async fn test_deposit_monthly_vesting() -> Result<(), TransportError> {
|
|||
assert_eq!(after_withdraw.vault, 0);
|
||||
assert_eq!(after_withdraw.deposit, 0);
|
||||
|
||||
addin.close_deposit(&voter, &voter_authority, 0).await.unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -194,6 +194,17 @@ async fn test_deposit_no_locking() -> Result<(), TransportError> {
|
|||
assert_eq!(after_withdraw2.vault, 7000);
|
||||
assert_eq!(after_withdraw2.deposit, 0);
|
||||
|
||||
// Close the empty deposit (closing deposits 1 and 2 fails)
|
||||
addin.close_deposit(&voter, &voter_authority, 2).await.expect_err("deposit not in use");
|
||||
addin.close_deposit(&voter, &voter_authority, 1).await.expect_err("deposit not empty");
|
||||
addin.close_deposit(&voter, &voter_authority, 0).await.unwrap();
|
||||
|
||||
let after_close = get_balances(0).await;
|
||||
assert_eq!(initial.token, after_close.token + after_close.vault);
|
||||
assert_eq!(after_close.voter_weight, after_close.vault);
|
||||
assert_eq!(after_close.vault, 7000);
|
||||
assert_eq!(after_close.deposit, 0);
|
||||
|
||||
// check that the voter2 account is still at 0
|
||||
let voter2_balances = balances(
|
||||
&context,
|
||||
|
@ -236,5 +247,26 @@ async fn test_deposit_no_locking() -> Result<(), TransportError> {
|
|||
assert_eq!(voter2_balances.voter_weight, 1000);
|
||||
assert_eq!(voter2_balances.vault, 8000);
|
||||
|
||||
// when voter1 deposits again, they can reuse deposit index 0
|
||||
addin
|
||||
.create_deposit(
|
||||
®istrar,
|
||||
&voter,
|
||||
&mngo_rate,
|
||||
&voter_authority,
|
||||
reference_account,
|
||||
governance_registry::account::LockupKind::Monthly,
|
||||
3000,
|
||||
1,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let after_reuse = get_balances(0).await;
|
||||
assert_eq!(initial.token, after_reuse.token + 7000 + 3000);
|
||||
assert_eq!(after_reuse.voter_weight, 7000 + 3000);
|
||||
assert_eq!(after_reuse.vault, 8000 + 3000);
|
||||
assert_eq!(after_reuse.deposit, 3000);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue