stake.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. use anchor_lang::{
  2. context::CpiContext,
  3. solana_program::{
  4. account_info::AccountInfo,
  5. pubkey::Pubkey,
  6. stake::{
  7. self,
  8. program::ID,
  9. state::{StakeAuthorize, StakeState},
  10. },
  11. },
  12. Accounts, Result,
  13. };
  14. use borsh::BorshDeserialize;
  15. use std::ops::Deref;
  16. // CPI functions
  17. pub fn authorize<'info>(
  18. ctx: CpiContext<'_, '_, '_, 'info, Authorize<'info>>,
  19. stake_authorize: StakeAuthorize,
  20. custodian: Option<AccountInfo<'info>>,
  21. ) -> Result<()> {
  22. let ix = stake::instruction::authorize(
  23. ctx.accounts.stake.key,
  24. ctx.accounts.authorized.key,
  25. ctx.accounts.new_authorized.key,
  26. stake_authorize,
  27. custodian.as_ref().map(|c| c.key),
  28. );
  29. let mut account_infos = vec![
  30. ctx.accounts.stake,
  31. ctx.accounts.clock,
  32. ctx.accounts.authorized,
  33. ];
  34. if let Some(c) = custodian {
  35. account_infos.push(c);
  36. }
  37. solana_program::program::invoke_signed(&ix, &account_infos, ctx.signer_seeds)
  38. .map_err(Into::into)
  39. }
  40. pub fn withdraw<'info>(
  41. ctx: CpiContext<'_, '_, '_, 'info, Withdraw<'info>>,
  42. amount: u64,
  43. custodian: Option<AccountInfo<'info>>,
  44. ) -> Result<()> {
  45. let ix = stake::instruction::withdraw(
  46. ctx.accounts.stake.key,
  47. ctx.accounts.withdrawer.key,
  48. ctx.accounts.to.key,
  49. amount,
  50. custodian.as_ref().map(|c| c.key),
  51. );
  52. let mut account_infos = vec![
  53. ctx.accounts.stake,
  54. ctx.accounts.to,
  55. ctx.accounts.clock,
  56. ctx.accounts.stake_history,
  57. ctx.accounts.withdrawer,
  58. ];
  59. if let Some(c) = custodian {
  60. account_infos.push(c);
  61. }
  62. solana_program::program::invoke_signed(&ix, &account_infos, ctx.signer_seeds)
  63. .map_err(Into::into)
  64. }
  65. pub fn deactivate_stake<'info>(
  66. ctx: CpiContext<'_, '_, '_, 'info, DeactivateStake<'info>>,
  67. ) -> Result<()> {
  68. let ix = stake::instruction::deactivate_stake(ctx.accounts.stake.key, ctx.accounts.staker.key);
  69. solana_program::program::invoke_signed(
  70. &ix,
  71. &[ctx.accounts.stake, ctx.accounts.clock, ctx.accounts.staker],
  72. ctx.signer_seeds,
  73. )
  74. .map_err(Into::into)
  75. }
  76. // CPI accounts
  77. #[derive(Accounts)]
  78. pub struct Authorize<'info> {
  79. /// The stake account to be updated
  80. pub stake: AccountInfo<'info>,
  81. /// The existing authority
  82. pub authorized: AccountInfo<'info>,
  83. /// The new authority to replace the existing authority
  84. pub new_authorized: AccountInfo<'info>,
  85. /// Clock sysvar
  86. pub clock: AccountInfo<'info>,
  87. }
  88. #[derive(Accounts)]
  89. pub struct Withdraw<'info> {
  90. /// The stake account to be updated
  91. pub stake: AccountInfo<'info>,
  92. /// The stake account's withdraw authority
  93. pub withdrawer: AccountInfo<'info>,
  94. /// Account to send withdrawn lamports to
  95. pub to: AccountInfo<'info>,
  96. /// Clock sysvar
  97. pub clock: AccountInfo<'info>,
  98. /// StakeHistory sysvar
  99. pub stake_history: AccountInfo<'info>,
  100. }
  101. #[derive(Accounts)]
  102. pub struct DeactivateStake<'info> {
  103. /// The stake account to be deactivated
  104. pub stake: AccountInfo<'info>,
  105. /// The stake account's stake authority
  106. pub staker: AccountInfo<'info>,
  107. /// Clock sysvar
  108. pub clock: AccountInfo<'info>,
  109. }
  110. // State
  111. #[derive(Clone)]
  112. pub struct StakeAccount(StakeState);
  113. impl anchor_lang::AccountDeserialize for StakeAccount {
  114. fn try_deserialize(buf: &mut &[u8]) -> anchor_lang::Result<Self> {
  115. Self::try_deserialize_unchecked(buf)
  116. }
  117. fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result<Self> {
  118. StakeState::deserialize(buf).map(Self).map_err(Into::into)
  119. }
  120. }
  121. impl anchor_lang::AccountSerialize for StakeAccount {}
  122. impl anchor_lang::Owner for StakeAccount {
  123. fn owner() -> Pubkey {
  124. ID
  125. }
  126. }
  127. impl Deref for StakeAccount {
  128. type Target = StakeState;
  129. fn deref(&self) -> &Self::Target {
  130. &self.0
  131. }
  132. }
  133. #[derive(Clone)]
  134. pub struct Stake;
  135. impl anchor_lang::Id for Stake {
  136. fn id() -> Pubkey {
  137. ID
  138. }
  139. }