use crate::state::{AssociatedProgram, SerializableActions};
pub mod delegate_instructions;
pub mod migrate;
pub mod profile_instructions;
pub mod project_instructions;
pub mod public_info_instructions;
pub mod user_instructions;
pub use {
delegate_instructions::*, migrate::*, profile_instructions::*, project_instructions::*,
public_info_instructions::*, user_instructions::*,
};
use {
crate::{
assertions::assert_authority,
errors::ErrorCode,
state::{ActionType, DelegateAuthority, Project, Service},
},
anchor_lang::{prelude::*, solana_program},
};
pub fn collect_payment<'info>(
fee: u64,
payer: AccountInfo<'info>,
vault: AccountInfo<'info>,
system_program: AccountInfo<'info>,
) -> Result<()> {
if !crate::constants::is_sandbox() {
if String::from("EE67X262V2CXa68oa65fn2KLzkn8hEEvwGc9aG6aCh2C") != vault.key().to_string() {
panic!("Invalid Vault key")
}
solana_program::program::invoke(
&solana_program::system_instruction::transfer(payer.key, vault.key, fee),
&[payer, vault, system_program],
)?;
}
Ok(())
}
pub fn platform_gate_fn<'info>(
serializable_action: SerializableActions,
service: Option<(u8, Pubkey)>,
project: &Account<'info, Project>,
signer_key: Pubkey,
payer: AccountInfo<'info>,
vault: AccountInfo<'info>,
delegate_authority: &Option<Account<'info, DelegateAuthority>>,
system_program: AccountInfo<'info>,
instructions_sysvar: AccountInfo<'info>,
program_id: Pubkey,
) -> Result<()> {
let action = serializable_action.to_action();
let fee = action.fee;
let ix_program_key =
anchor_lang::solana_program::sysvar::instructions::get_instruction_relative(
0,
&instructions_sysvar,
)
.unwrap()
.program_id;
let is_cpi = program_id.eq(&ix_program_key);
if is_cpi {
let associated_programs: Vec<AssociatedProgram> = vec![
crate::constants::known_programs(),
project.associated_programs.clone(),
]
.concat();
let program_ctx = associated_programs
.iter()
.find(|p| (p.address).eq(&ix_program_key));
if let Some(program_ctx) = program_ctx {
if let ActionType::Restricted { delegations: _ } = action.action_type {
for action_ctx in program_ctx.trusted_actions.iter() {
if action_ctx.is_equal(&action) {
return collect_payment(fee, payer, vault, system_program);
}
}
}
} else {
return Err(ErrorCode::UnknownCPI.into());
}
}
if service.is_some() && service.unwrap().1.eq(&Pubkey::default()) {
if project.driver.ne(&signer_key) {
return Err(ErrorCode::Unauthorized.into());
}
} else {
let mut index: Option<u8> = None;
if let Some(service) = service {
let service_id = match project.services[service.0 as usize] {
Service::Assembler { assembler_id } => assembler_id,
Service::AssetManager { asset_manager_id } => asset_manager_id,
Service::Missions { pool_id } => pool_id,
Service::Raffles { pool_id } => pool_id,
Service::Staking { pool_id } => pool_id,
Service::GuildKit { kit_id } => kit_id,
_ => Pubkey::default(),
};
if service_id == service.1 {
index = Some(service.0 as u8);
}
}
assert_authority(
action,
index,
signer_key,
if delegate_authority.is_none() {
Some(project.authority)
} else {
None
},
delegate_authority,
)?;
}
collect_payment(fee, payer, vault, system_program)
}
#[derive(Accounts)]
pub struct PlatformGate<'info> {
#[account()]
pub project: Account<'info, Project>,
#[account()]
pub delegate_authority: Option<Account<'info, DelegateAuthority>>,
#[account(mut)]
pub payer: Signer<'info>,
pub signer: Signer<'info>,
#[account(mut)]
pub vault: AccountInfo<'info>,
pub system_program: Program<'info, System>,
#[account(address = anchor_lang::solana_program::sysvar::instructions::ID)]
pub instructions_sysvar: AccountInfo<'info>,
}
#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub struct PlatformGateArgs {
pub action: SerializableActions,
pub service: Option<(u8, Pubkey)>,
pub program_id: Pubkey,
}
pub fn platform_gate(ctx: Context<PlatformGate>, args: PlatformGateArgs) -> Result<()> {
platform_gate_fn(
args.action,
args.service,
&ctx.accounts.project,
ctx.accounts.signer.key(),
ctx.accounts.payer.to_account_info(),
ctx.accounts.vault.to_account_info(),
&ctx.accounts.delegate_authority,
ctx.accounts.system_program.to_account_info(),
ctx.accounts.instructions_sysvar.to_account_info(),
args.program_id,
)
}