From 2cc39ab06b3053f5b098688bcd6d287f3e20b787 Mon Sep 17 00:00:00 2001 From: Andrew Schonfeld Date: Tue, 16 Aug 2022 18:22:38 -0400 Subject: [PATCH] VoteProgram.safeWithdraw function to safeguard against accidental vote account closures (#26586) feat: safe withdraw function Co-authored-by: aschonfeld --- src/programs/vote.ts | 21 +++++++++++++++++++++ test/program-tests/vote.test.ts | 15 +++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/programs/vote.ts b/src/programs/vote.ts index 6cd16671a977..db1a111da919 100644 --- a/src/programs/vote.ts +++ b/src/programs/vote.ts @@ -410,4 +410,25 @@ export class VoteProgram { data, }); } + + /** + * Generate a transaction to withdraw safely from a Vote account. + * + * This function was created as a safeguard for vote accounts running validators, `safeWithdraw` + * checks that the withdraw amount will not exceed the specified balance while leaving enough left + * to cover rent. If you wish to close the vote account by withdrawing the full amount, call the + * `withdraw` method directly. + */ + static safeWithdraw( + params: WithdrawFromVoteAccountParams, + currentVoteAccountBalance: number, + rentExemptMinimum: number, + ): Transaction { + if (params.lamports > currentVoteAccountBalance - rentExemptMinimum) { + throw new Error( + 'Withdraw will leave vote account with insuffcient funds.', + ); + } + return VoteProgram.withdraw(params); + } } diff --git a/test/program-tests/vote.test.ts b/test/program-tests/vote.test.ts index 596e6e401b4f..6cd349a0c3a7 100644 --- a/test/program-tests/vote.test.ts +++ b/test/program-tests/vote.test.ts @@ -167,6 +167,21 @@ describe('VoteProgram', () => { // Withdraw from Vote account let recipient = Keypair.generate(); + const voteBalance = await connection.getBalance(newVoteAccount.publicKey); + + expect(() => + VoteProgram.safeWithdraw( + { + votePubkey: newVoteAccount.publicKey, + authorizedWithdrawerPubkey: authorized.publicKey, + lamports: voteBalance - minimumAmount + 1, + toPubkey: recipient.publicKey, + }, + voteBalance, + minimumAmount, + ), + ).to.throw('Withdraw will leave vote account with insuffcient funds.'); + let withdraw = VoteProgram.withdraw({ votePubkey: newVoteAccount.publicKey, authorizedWithdrawerPubkey: authorized.publicKey,