registry: Use correct timelock and transition entity state on reward claim (#59)

This commit is contained in:
Armani Ferrante 2020-12-10 00:04:00 -08:00 committed by GitHub
parent d2d5e287d5
commit 0704adde56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 115 additions and 94 deletions

View File

@ -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,20 +43,29 @@ pub fn handler(
spt_acc_infos.push(next_account_info(acc_infos)?);
}
let ctx = EntityContext {
entity_acc_info,
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,
ref clock,
} = 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,
clock_acc_info,
spt_acc_infos: spt_acc_infos.as_ref(),
})?;
Member::unpack_mut(
@ -81,9 +92,9 @@ pub fn handler(
})
.map_err(Into::into)
},
)?;
Ok(())
)
.map_err(Into::into)
})
}
fn access_control(req: AccessControlRequest) -> Result<AccessControlResponse, RegistryError> {
@ -92,13 +103,14 @@ fn access_control(req: AccessControlRequest) -> Result<AccessControlResponse, Re
let AccessControlRequest {
program_id,
cursor,
registrar,
entity,
signer_acc_info,
registrar_acc_info,
entity_acc_info,
member_acc_info,
vendor_acc_info,
spt_acc_infos,
clock_acc_info,
} = req;
// Authorization. Must be either the beneficiary or the node leader.
@ -107,9 +119,6 @@ fn access_control(req: AccessControlRequest) -> Result<AccessControlResponse, Re
}
// Account validation.
let clock = access_control::clock(clock_acc_info)?;
let registrar = access_control::registrar(registrar_acc_info, program_id)?;
let entity = access_control::entity(entity_acc_info, registrar_acc_info, program_id)?;
let member = access_control::member_belongs_to(
member_acc_info,
registrar_acc_info,
@ -159,11 +168,7 @@ fn access_control(req: AccessControlRequest) -> Result<AccessControlResponse, Re
return Err(RegistryErrorCode::Unauthorized)?;
}
Ok(AccessControlResponse {
vendor,
spts,
clock,
})
Ok(AccessControlResponse { vendor, spts })
}
fn state_transition(req: StateTransitionRequest) -> 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<TokenAccount>,
clock: sysvar::clock::Clock,
}
struct StateTransitionRequest<'a, 'b, 'c> {

View File

@ -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,12 +29,22 @@ 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 ctx = EntityContext {
entity_acc_info,
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,
@ -45,7 +57,9 @@ pub fn handler(
vendor_acc_info,
token_acc_info,
cursor,
spt_acc_infos,
registrar,
entity,
spt_acc_infos: spt_acc_infos.as_ref(),
})?;
Member::unpack_mut(
@ -65,9 +79,9 @@ pub fn handler(
})
.map_err(Into::into)
},
)?;
Ok(())
)
.map_err(Into::into)
})
}
fn access_control(req: AccessControlRequest) -> Result<AccessControlResponse, RegistryError> {
@ -76,6 +90,8 @@ fn access_control(req: AccessControlRequest) -> Result<AccessControlResponse, Re
let AccessControlRequest {
program_id,
cursor,
registrar,
entity,
signer_acc_info,
registrar_acc_info,
entity_acc_info,
@ -91,8 +107,6 @@ fn access_control(req: AccessControlRequest) -> Result<AccessControlResponse, Re
}
// Account validation.
let registrar = access_control::registrar(registrar_acc_info, program_id)?;
let entity = access_control::entity(entity_acc_info, registrar_acc_info, program_id)?;
let member = access_control::member_belongs_to(
member_acc_info,
registrar_acc_info,
@ -190,16 +204,18 @@ fn state_transition(req: StateTransitionRequest) -> 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 {

View File

@ -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;

View File

@ -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;