From 0704adde562882921af1b9e43358f8e398ac259f Mon Sep 17 00:00:00 2001 From: Armani Ferrante Date: Thu, 10 Dec 2020 00:04:00 -0800 Subject: [PATCH] registry: Use correct timelock and transition entity state on reward claim (#59) --- registry/program/src/claim_locked_reward.rs | 113 +++++++++--------- registry/program/src/claim_unlocked_reward.rs | 92 ++++++++------ .../program/src/start_stake_withdrawal.rs | 2 +- registry/tests/lifecycle.rs | 2 +- 4 files changed, 115 insertions(+), 94 deletions(-) diff --git a/registry/program/src/claim_locked_reward.rs b/registry/program/src/claim_locked_reward.rs index 3500328..70fc5a5 100644 --- a/registry/program/src/claim_locked_reward.rs +++ b/registry/program/src/claim_locked_reward.rs @@ -1,13 +1,15 @@ +use crate::common::entity::{with_entity, EntityContext}; use serum_common::pack::Pack; use serum_lockup::instruction::LockupInstruction; use serum_registry::access_control; -use serum_registry::accounts::{EntityState, LockedRewardVendor, Member}; +use serum_registry::accounts::{Entity, EntityState, LockedRewardVendor, Member, Registrar}; use serum_registry::error::{RegistryError, RegistryErrorCode}; use solana_program::msg; use solana_sdk::account_info::{next_account_info, AccountInfo}; use solana_sdk::instruction::{AccountMeta, Instruction}; use solana_sdk::pubkey::Pubkey; use solana_sdk::sysvar; +use solana_sdk::sysvar::clock::Clock; use spl_token::state::Account as TokenAccount; #[inline(never)] @@ -41,49 +43,58 @@ pub fn handler( spt_acc_infos.push(next_account_info(acc_infos)?); } - let AccessControlResponse { - ref vendor, - ref spts, - ref clock, - } = access_control(AccessControlRequest { - program_id, - signer_acc_info, - registrar_acc_info, + let ctx = EntityContext { entity_acc_info, - member_acc_info, - vendor_acc_info, - cursor, - spt_acc_infos, + registrar_acc_info, clock_acc_info, - })?; + program_id, + }; + with_entity(ctx, &mut |entity: &mut Entity, + registrar: &Registrar, + ref clock: &Clock| { + let AccessControlResponse { + ref vendor, + ref spts, + } = access_control(AccessControlRequest { + program_id, + entity, + registrar, + signer_acc_info, + registrar_acc_info, + entity_acc_info, + member_acc_info, + vendor_acc_info, + cursor, + spt_acc_infos: spt_acc_infos.as_ref(), + })?; - Member::unpack_mut( - &mut member_acc_info.try_borrow_mut_data()?, - &mut |member: &mut Member| { - state_transition(StateTransitionRequest { - cursor, - nonce, - member, - vendor, - registrar_acc_info, - vendor_acc_info, - vendor_vault_authority_acc_info, - safe_acc_info, - lockup_program_acc_info, - vesting_acc_info, - vesting_vault_acc_info, - vendor_vault_acc_info, - token_program_acc_info, - rent_acc_info, - clock_acc_info, - clock, - spts, - }) - .map_err(Into::into) - }, - )?; - - Ok(()) + Member::unpack_mut( + &mut member_acc_info.try_borrow_mut_data()?, + &mut |member: &mut Member| { + state_transition(StateTransitionRequest { + cursor, + nonce, + member, + vendor, + registrar_acc_info, + vendor_acc_info, + vendor_vault_authority_acc_info, + safe_acc_info, + lockup_program_acc_info, + vesting_acc_info, + vesting_vault_acc_info, + vendor_vault_acc_info, + token_program_acc_info, + rent_acc_info, + clock_acc_info, + clock, + spts, + }) + .map_err(Into::into) + }, + ) + .map_err(Into::into) + }) } fn access_control(req: AccessControlRequest) -> Result { @@ -92,13 +103,14 @@ fn access_control(req: AccessControlRequest) -> Result Result Result Result<(), RegistryError> { @@ -259,22 +264,22 @@ fn state_transition(req: StateTransitionRequest) -> Result<(), RegistryError> { Ok(()) } -struct AccessControlRequest<'a, 'b> { +struct AccessControlRequest<'a, 'b, 'c> { program_id: &'a Pubkey, cursor: u32, + entity: &'c Entity, + registrar: &'c Registrar, signer_acc_info: &'a AccountInfo<'b>, entity_acc_info: &'a AccountInfo<'b>, member_acc_info: &'a AccountInfo<'b>, registrar_acc_info: &'a AccountInfo<'b>, vendor_acc_info: &'a AccountInfo<'b>, - spt_acc_infos: Vec<&'a AccountInfo<'b>>, - clock_acc_info: &'a AccountInfo<'b>, + spt_acc_infos: &'c [&'a AccountInfo<'b>], } struct AccessControlResponse { vendor: LockedRewardVendor, spts: Vec, - clock: sysvar::clock::Clock, } struct StateTransitionRequest<'a, 'b, 'c> { diff --git a/registry/program/src/claim_unlocked_reward.rs b/registry/program/src/claim_unlocked_reward.rs index c3be107..590e8f7 100644 --- a/registry/program/src/claim_unlocked_reward.rs +++ b/registry/program/src/claim_unlocked_reward.rs @@ -1,11 +1,13 @@ +use crate::common::entity::{with_entity, EntityContext}; use serum_common::pack::Pack; use serum_common::program::invoke_token_transfer; use serum_registry::access_control; -use serum_registry::accounts::{EntityState, Member, UnlockedRewardVendor}; +use serum_registry::accounts::{Entity, EntityState, Member, Registrar, UnlockedRewardVendor}; use serum_registry::error::{RegistryError, RegistryErrorCode}; use solana_program::msg; use solana_sdk::account_info::{next_account_info, AccountInfo}; use solana_sdk::pubkey::Pubkey; +use solana_sdk::sysvar::clock::Clock; use spl_token::state::Account as TokenAccount; #[inline(never)] @@ -27,47 +29,59 @@ pub fn handler( let vendor_vault_authority_acc_info = next_account_info(acc_infos)?; let token_acc_info = next_account_info(acc_infos)?; let token_program_acc_info = next_account_info(acc_infos)?; + let clock_acc_info = next_account_info(acc_infos)?; let mut spt_acc_infos = vec![]; while acc_infos.len() > 0 { spt_acc_infos.push(next_account_info(acc_infos)?); } - let AccessControlResponse { - ref vendor, - ref spts, - } = access_control(AccessControlRequest { - program_id, - signer_acc_info, - registrar_acc_info, + let ctx = EntityContext { entity_acc_info, - member_acc_info, - vendor_acc_info, - token_acc_info, - cursor, - spt_acc_infos, - })?; + registrar_acc_info, + clock_acc_info, + program_id, + }; + with_entity(ctx, &mut |entity: &mut Entity, + registrar: &Registrar, + _clock: &Clock| { + let AccessControlResponse { + ref vendor, + ref spts, + } = access_control(AccessControlRequest { + program_id, + signer_acc_info, + registrar_acc_info, + entity_acc_info, + member_acc_info, + vendor_acc_info, + token_acc_info, + cursor, + registrar, + entity, + spt_acc_infos: spt_acc_infos.as_ref(), + })?; - Member::unpack_mut( - &mut member_acc_info.try_borrow_mut_data()?, - &mut |member: &mut Member| { - state_transition(StateTransitionRequest { - cursor, - member, - vendor, - registrar_acc_info, - vendor_acc_info, - vendor_vault_authority_acc_info, - vendor_vault_acc_info, - token_acc_info, - token_program_acc_info, - spts, - }) - .map_err(Into::into) - }, - )?; - - Ok(()) + Member::unpack_mut( + &mut member_acc_info.try_borrow_mut_data()?, + &mut |member: &mut Member| { + state_transition(StateTransitionRequest { + cursor, + member, + vendor, + registrar_acc_info, + vendor_acc_info, + vendor_vault_authority_acc_info, + vendor_vault_acc_info, + token_acc_info, + token_program_acc_info, + spts, + }) + .map_err(Into::into) + }, + ) + .map_err(Into::into) + }) } fn access_control(req: AccessControlRequest) -> Result { @@ -76,6 +90,8 @@ fn access_control(req: AccessControlRequest) -> Result Result Result<(), RegistryError> { Ok(()) } -struct AccessControlRequest<'a, 'b> { +struct AccessControlRequest<'a, 'b, 'c> { program_id: &'a Pubkey, cursor: u32, + registrar: &'c Registrar, + entity: &'c Entity, signer_acc_info: &'a AccountInfo<'b>, entity_acc_info: &'a AccountInfo<'b>, member_acc_info: &'a AccountInfo<'b>, registrar_acc_info: &'a AccountInfo<'b>, vendor_acc_info: &'a AccountInfo<'b>, token_acc_info: &'a AccountInfo<'b>, - spt_acc_infos: Vec<&'a AccountInfo<'b>>, + spt_acc_infos: &'c [&'a AccountInfo<'b>], } struct AccessControlResponse { diff --git a/registry/program/src/start_stake_withdrawal.rs b/registry/program/src/start_stake_withdrawal.rs index d6562b9..f84e4b6 100644 --- a/registry/program/src/start_stake_withdrawal.rs +++ b/registry/program/src/start_stake_withdrawal.rs @@ -231,7 +231,7 @@ fn state_transition(req: StateTransitionRequest) -> Result<(), RegistryError> { pending_withdrawal.burned = false; pending_withdrawal.member = *member_acc_info.key; pending_withdrawal.start_ts = clock.unix_timestamp; - pending_withdrawal.end_ts = clock.unix_timestamp + registrar.deactivation_timelock; + pending_withdrawal.end_ts = clock.unix_timestamp + registrar.withdrawal_timelock; pending_withdrawal.amount = token_amount; pending_withdrawal.pool = *pool_mint_acc_info.key; pending_withdrawal.balance_id = *balance_id; diff --git a/registry/tests/lifecycle.rs b/registry/tests/lifecycle.rs index 1c08882..6c92bfe 100644 --- a/registry/tests/lifecycle.rs +++ b/registry/tests/lifecycle.rs @@ -35,7 +35,7 @@ fn lifecycle() { } = genesis; // Initialize the registrar. - let withdrawal_timelock = 1234; + let withdrawal_timelock = 10; let deactivation_timelock = 10; let reward_activation_threshold = 10; let max_stake_per_entity = 100_000_000_000_000;