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_common::pack::Pack;
|
||||||
use serum_lockup::instruction::LockupInstruction;
|
use serum_lockup::instruction::LockupInstruction;
|
||||||
use serum_registry::access_control;
|
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 serum_registry::error::{RegistryError, RegistryErrorCode};
|
||||||
use solana_program::msg;
|
use solana_program::msg;
|
||||||
use solana_sdk::account_info::{next_account_info, AccountInfo};
|
use solana_sdk::account_info::{next_account_info, AccountInfo};
|
||||||
use solana_sdk::instruction::{AccountMeta, Instruction};
|
use solana_sdk::instruction::{AccountMeta, Instruction};
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::sysvar;
|
use solana_sdk::sysvar;
|
||||||
|
use solana_sdk::sysvar::clock::Clock;
|
||||||
use spl_token::state::Account as TokenAccount;
|
use spl_token::state::Account as TokenAccount;
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
|
@ -41,49 +43,58 @@ pub fn handler(
|
||||||
spt_acc_infos.push(next_account_info(acc_infos)?);
|
spt_acc_infos.push(next_account_info(acc_infos)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
let AccessControlResponse {
|
let ctx = EntityContext {
|
||||||
ref vendor,
|
|
||||||
ref spts,
|
|
||||||
ref clock,
|
|
||||||
} = access_control(AccessControlRequest {
|
|
||||||
program_id,
|
|
||||||
signer_acc_info,
|
|
||||||
registrar_acc_info,
|
|
||||||
entity_acc_info,
|
entity_acc_info,
|
||||||
member_acc_info,
|
registrar_acc_info,
|
||||||
vendor_acc_info,
|
|
||||||
cursor,
|
|
||||||
spt_acc_infos,
|
|
||||||
clock_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(
|
Member::unpack_mut(
|
||||||
&mut member_acc_info.try_borrow_mut_data()?,
|
&mut member_acc_info.try_borrow_mut_data()?,
|
||||||
&mut |member: &mut Member| {
|
&mut |member: &mut Member| {
|
||||||
state_transition(StateTransitionRequest {
|
state_transition(StateTransitionRequest {
|
||||||
cursor,
|
cursor,
|
||||||
nonce,
|
nonce,
|
||||||
member,
|
member,
|
||||||
vendor,
|
vendor,
|
||||||
registrar_acc_info,
|
registrar_acc_info,
|
||||||
vendor_acc_info,
|
vendor_acc_info,
|
||||||
vendor_vault_authority_acc_info,
|
vendor_vault_authority_acc_info,
|
||||||
safe_acc_info,
|
safe_acc_info,
|
||||||
lockup_program_acc_info,
|
lockup_program_acc_info,
|
||||||
vesting_acc_info,
|
vesting_acc_info,
|
||||||
vesting_vault_acc_info,
|
vesting_vault_acc_info,
|
||||||
vendor_vault_acc_info,
|
vendor_vault_acc_info,
|
||||||
token_program_acc_info,
|
token_program_acc_info,
|
||||||
rent_acc_info,
|
rent_acc_info,
|
||||||
clock_acc_info,
|
clock_acc_info,
|
||||||
clock,
|
clock,
|
||||||
spts,
|
spts,
|
||||||
})
|
})
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
},
|
},
|
||||||
)?;
|
)
|
||||||
|
.map_err(Into::into)
|
||||||
Ok(())
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn access_control(req: AccessControlRequest) -> Result<AccessControlResponse, RegistryError> {
|
fn access_control(req: AccessControlRequest) -> Result<AccessControlResponse, RegistryError> {
|
||||||
|
@ -92,13 +103,14 @@ fn access_control(req: AccessControlRequest) -> Result<AccessControlResponse, Re
|
||||||
let AccessControlRequest {
|
let AccessControlRequest {
|
||||||
program_id,
|
program_id,
|
||||||
cursor,
|
cursor,
|
||||||
|
registrar,
|
||||||
|
entity,
|
||||||
signer_acc_info,
|
signer_acc_info,
|
||||||
registrar_acc_info,
|
registrar_acc_info,
|
||||||
entity_acc_info,
|
entity_acc_info,
|
||||||
member_acc_info,
|
member_acc_info,
|
||||||
vendor_acc_info,
|
vendor_acc_info,
|
||||||
spt_acc_infos,
|
spt_acc_infos,
|
||||||
clock_acc_info,
|
|
||||||
} = req;
|
} = req;
|
||||||
|
|
||||||
// Authorization. Must be either the beneficiary or the node leader.
|
// Authorization. Must be either the beneficiary or the node leader.
|
||||||
|
@ -107,9 +119,6 @@ fn access_control(req: AccessControlRequest) -> Result<AccessControlResponse, Re
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account validation.
|
// 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(
|
let member = access_control::member_belongs_to(
|
||||||
member_acc_info,
|
member_acc_info,
|
||||||
registrar_acc_info,
|
registrar_acc_info,
|
||||||
|
@ -159,11 +168,7 @@ fn access_control(req: AccessControlRequest) -> Result<AccessControlResponse, Re
|
||||||
return Err(RegistryErrorCode::Unauthorized)?;
|
return Err(RegistryErrorCode::Unauthorized)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(AccessControlResponse {
|
Ok(AccessControlResponse { vendor, spts })
|
||||||
vendor,
|
|
||||||
spts,
|
|
||||||
clock,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn state_transition(req: StateTransitionRequest) -> Result<(), RegistryError> {
|
fn state_transition(req: StateTransitionRequest) -> Result<(), RegistryError> {
|
||||||
|
@ -259,22 +264,22 @@ fn state_transition(req: StateTransitionRequest) -> Result<(), RegistryError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AccessControlRequest<'a, 'b> {
|
struct AccessControlRequest<'a, 'b, 'c> {
|
||||||
program_id: &'a Pubkey,
|
program_id: &'a Pubkey,
|
||||||
cursor: u32,
|
cursor: u32,
|
||||||
|
entity: &'c Entity,
|
||||||
|
registrar: &'c Registrar,
|
||||||
signer_acc_info: &'a AccountInfo<'b>,
|
signer_acc_info: &'a AccountInfo<'b>,
|
||||||
entity_acc_info: &'a AccountInfo<'b>,
|
entity_acc_info: &'a AccountInfo<'b>,
|
||||||
member_acc_info: &'a AccountInfo<'b>,
|
member_acc_info: &'a AccountInfo<'b>,
|
||||||
registrar_acc_info: &'a AccountInfo<'b>,
|
registrar_acc_info: &'a AccountInfo<'b>,
|
||||||
vendor_acc_info: &'a AccountInfo<'b>,
|
vendor_acc_info: &'a AccountInfo<'b>,
|
||||||
spt_acc_infos: Vec<&'a AccountInfo<'b>>,
|
spt_acc_infos: &'c [&'a AccountInfo<'b>],
|
||||||
clock_acc_info: &'a AccountInfo<'b>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AccessControlResponse {
|
struct AccessControlResponse {
|
||||||
vendor: LockedRewardVendor,
|
vendor: LockedRewardVendor,
|
||||||
spts: Vec<TokenAccount>,
|
spts: Vec<TokenAccount>,
|
||||||
clock: sysvar::clock::Clock,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StateTransitionRequest<'a, 'b, 'c> {
|
struct StateTransitionRequest<'a, 'b, 'c> {
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
|
use crate::common::entity::{with_entity, EntityContext};
|
||||||
use serum_common::pack::Pack;
|
use serum_common::pack::Pack;
|
||||||
use serum_common::program::invoke_token_transfer;
|
use serum_common::program::invoke_token_transfer;
|
||||||
use serum_registry::access_control;
|
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 serum_registry::error::{RegistryError, RegistryErrorCode};
|
||||||
use solana_program::msg;
|
use solana_program::msg;
|
||||||
use solana_sdk::account_info::{next_account_info, AccountInfo};
|
use solana_sdk::account_info::{next_account_info, AccountInfo};
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
use solana_sdk::sysvar::clock::Clock;
|
||||||
use spl_token::state::Account as TokenAccount;
|
use spl_token::state::Account as TokenAccount;
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
|
@ -27,47 +29,59 @@ pub fn handler(
|
||||||
let vendor_vault_authority_acc_info = next_account_info(acc_infos)?;
|
let vendor_vault_authority_acc_info = next_account_info(acc_infos)?;
|
||||||
let token_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 token_program_acc_info = next_account_info(acc_infos)?;
|
||||||
|
let clock_acc_info = next_account_info(acc_infos)?;
|
||||||
|
|
||||||
let mut spt_acc_infos = vec![];
|
let mut spt_acc_infos = vec![];
|
||||||
while acc_infos.len() > 0 {
|
while acc_infos.len() > 0 {
|
||||||
spt_acc_infos.push(next_account_info(acc_infos)?);
|
spt_acc_infos.push(next_account_info(acc_infos)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
let AccessControlResponse {
|
let ctx = EntityContext {
|
||||||
ref vendor,
|
|
||||||
ref spts,
|
|
||||||
} = access_control(AccessControlRequest {
|
|
||||||
program_id,
|
|
||||||
signer_acc_info,
|
|
||||||
registrar_acc_info,
|
|
||||||
entity_acc_info,
|
entity_acc_info,
|
||||||
member_acc_info,
|
registrar_acc_info,
|
||||||
vendor_acc_info,
|
clock_acc_info,
|
||||||
token_acc_info,
|
program_id,
|
||||||
cursor,
|
};
|
||||||
spt_acc_infos,
|
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(
|
Member::unpack_mut(
|
||||||
&mut member_acc_info.try_borrow_mut_data()?,
|
&mut member_acc_info.try_borrow_mut_data()?,
|
||||||
&mut |member: &mut Member| {
|
&mut |member: &mut Member| {
|
||||||
state_transition(StateTransitionRequest {
|
state_transition(StateTransitionRequest {
|
||||||
cursor,
|
cursor,
|
||||||
member,
|
member,
|
||||||
vendor,
|
vendor,
|
||||||
registrar_acc_info,
|
registrar_acc_info,
|
||||||
vendor_acc_info,
|
vendor_acc_info,
|
||||||
vendor_vault_authority_acc_info,
|
vendor_vault_authority_acc_info,
|
||||||
vendor_vault_acc_info,
|
vendor_vault_acc_info,
|
||||||
token_acc_info,
|
token_acc_info,
|
||||||
token_program_acc_info,
|
token_program_acc_info,
|
||||||
spts,
|
spts,
|
||||||
})
|
})
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
},
|
},
|
||||||
)?;
|
)
|
||||||
|
.map_err(Into::into)
|
||||||
Ok(())
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn access_control(req: AccessControlRequest) -> Result<AccessControlResponse, RegistryError> {
|
fn access_control(req: AccessControlRequest) -> Result<AccessControlResponse, RegistryError> {
|
||||||
|
@ -76,6 +90,8 @@ fn access_control(req: AccessControlRequest) -> Result<AccessControlResponse, Re
|
||||||
let AccessControlRequest {
|
let AccessControlRequest {
|
||||||
program_id,
|
program_id,
|
||||||
cursor,
|
cursor,
|
||||||
|
registrar,
|
||||||
|
entity,
|
||||||
signer_acc_info,
|
signer_acc_info,
|
||||||
registrar_acc_info,
|
registrar_acc_info,
|
||||||
entity_acc_info,
|
entity_acc_info,
|
||||||
|
@ -91,8 +107,6 @@ fn access_control(req: AccessControlRequest) -> Result<AccessControlResponse, Re
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account validation.
|
// 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(
|
let member = access_control::member_belongs_to(
|
||||||
member_acc_info,
|
member_acc_info,
|
||||||
registrar_acc_info,
|
registrar_acc_info,
|
||||||
|
@ -190,16 +204,18 @@ fn state_transition(req: StateTransitionRequest) -> Result<(), RegistryError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AccessControlRequest<'a, 'b> {
|
struct AccessControlRequest<'a, 'b, 'c> {
|
||||||
program_id: &'a Pubkey,
|
program_id: &'a Pubkey,
|
||||||
cursor: u32,
|
cursor: u32,
|
||||||
|
registrar: &'c Registrar,
|
||||||
|
entity: &'c Entity,
|
||||||
signer_acc_info: &'a AccountInfo<'b>,
|
signer_acc_info: &'a AccountInfo<'b>,
|
||||||
entity_acc_info: &'a AccountInfo<'b>,
|
entity_acc_info: &'a AccountInfo<'b>,
|
||||||
member_acc_info: &'a AccountInfo<'b>,
|
member_acc_info: &'a AccountInfo<'b>,
|
||||||
registrar_acc_info: &'a AccountInfo<'b>,
|
registrar_acc_info: &'a AccountInfo<'b>,
|
||||||
vendor_acc_info: &'a AccountInfo<'b>,
|
vendor_acc_info: &'a AccountInfo<'b>,
|
||||||
token_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 {
|
struct AccessControlResponse {
|
||||||
|
|
|
@ -231,7 +231,7 @@ fn state_transition(req: StateTransitionRequest) -> Result<(), RegistryError> {
|
||||||
pending_withdrawal.burned = false;
|
pending_withdrawal.burned = false;
|
||||||
pending_withdrawal.member = *member_acc_info.key;
|
pending_withdrawal.member = *member_acc_info.key;
|
||||||
pending_withdrawal.start_ts = clock.unix_timestamp;
|
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.amount = token_amount;
|
||||||
pending_withdrawal.pool = *pool_mint_acc_info.key;
|
pending_withdrawal.pool = *pool_mint_acc_info.key;
|
||||||
pending_withdrawal.balance_id = *balance_id;
|
pending_withdrawal.balance_id = *balance_id;
|
||||||
|
|
|
@ -35,7 +35,7 @@ fn lifecycle() {
|
||||||
} = genesis;
|
} = genesis;
|
||||||
|
|
||||||
// Initialize the registrar.
|
// Initialize the registrar.
|
||||||
let withdrawal_timelock = 1234;
|
let withdrawal_timelock = 10;
|
||||||
let deactivation_timelock = 10;
|
let deactivation_timelock = 10;
|
||||||
let reward_activation_threshold = 10;
|
let reward_activation_threshold = 10;
|
||||||
let max_stake_per_entity = 100_000_000_000_000;
|
let max_stake_per_entity = 100_000_000_000_000;
|
||||||
|
|
Loading…
Reference in New Issue