registry: Use correct timelock and transition entity state on reward claim (#59)
This commit is contained in:
parent
d2d5e287d5
commit
0704adde56
|
@ -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<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> {
|
||||
|
|
|
@ -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<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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue