Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions dlp-api/src/instruction_builder/delegate_magic_fee_vault.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use dlp::{
discriminator::DlpDiscriminator,
pda::{
delegate_buffer_pda_from_delegated_account_and_owner_program,
delegation_metadata_pda_from_delegated_account,
delegation_record_pda_from_delegated_account,
magic_fee_vault_pda_from_validator,
validator_fees_vault_pda_from_validator,
},
};
use solana_program::{
instruction::{AccountMeta, Instruction},
pubkey::Pubkey,
system_program,
};

/// Delegates the magic fee vault PDA for a validator.
/// See [crate::processor::process_delegate_magic_fee_vault] for docs.
pub fn delegate_magic_fee_vault(
payer: Pubkey,
validator_identity: Pubkey,
) -> Instruction {
let validator_fees_vault =
validator_fees_vault_pda_from_validator(&validator_identity);
let magic_fee_vault =
magic_fee_vault_pda_from_validator(&validator_identity);
let delegate_buffer =
delegate_buffer_pda_from_delegated_account_and_owner_program(
&magic_fee_vault,
&dlp::id(),
);
let delegation_record =
delegation_record_pda_from_delegated_account(&magic_fee_vault);
let delegation_metadata =
delegation_metadata_pda_from_delegated_account(&magic_fee_vault);

Instruction {
program_id: dlp::id(),
accounts: vec![
AccountMeta::new(payer, true),
AccountMeta::new_readonly(validator_identity, true),
AccountMeta::new_readonly(validator_fees_vault, false),
AccountMeta::new(magic_fee_vault, false),
AccountMeta::new(delegate_buffer, false),
AccountMeta::new(delegation_record, false),
AccountMeta::new(delegation_metadata, false),
AccountMeta::new_readonly(system_program::id(), false),
AccountMeta::new_readonly(dlp::id(), false),
],
data: DlpDiscriminator::DelegateMagicFeeVault.to_vec(),
}
}
35 changes: 35 additions & 0 deletions dlp-api/src/instruction_builder/init_magic_fee_vault.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use dlp::{
discriminator::DlpDiscriminator,
pda::{
magic_fee_vault_pda_from_validator,
validator_fees_vault_pda_from_validator,
},
};
use solana_program::{
instruction::{AccountMeta, Instruction},
pubkey::Pubkey,
system_program,
};

/// Initialize a magic fee vault PDA for a validator.
/// See [crate::processor::process_init_magic_fee_vault] for docs.
pub fn init_magic_fee_vault(
payer: Pubkey,
validator_identity: Pubkey,
) -> Instruction {
let validator_fees_vault =
validator_fees_vault_pda_from_validator(&validator_identity);
let magic_fee_vault =
magic_fee_vault_pda_from_validator(&validator_identity);
Instruction {
program_id: dlp::id(),
accounts: vec![
AccountMeta::new(payer, true),
AccountMeta::new_readonly(validator_identity, true),
AccountMeta::new_readonly(validator_fees_vault, false),
AccountMeta::new(magic_fee_vault, false),
AccountMeta::new_readonly(system_program::id(), false),
],
data: DlpDiscriminator::InitMagicFeeVault.to_vec(),
}
}
4 changes: 4 additions & 0 deletions dlp-api/src/instruction_builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ mod commit_state;
mod commit_state_from_buffer;
mod delegate;
mod delegate_ephemeral_balance;
mod delegate_magic_fee_vault;
mod delegate_with_actions;
mod finalize;
mod init_magic_fee_vault;
mod init_protocol_fees_vault;
mod init_validator_fees_vault;
mod protocol_claim_fees;
Expand All @@ -34,8 +36,10 @@ pub use commit_state::*;
pub use commit_state_from_buffer::*;
pub use delegate::*;
pub use delegate_ephemeral_balance::*;
pub use delegate_magic_fee_vault::*;
pub use delegate_with_actions::*;
pub use finalize::*;
pub use init_magic_fee_vault::*;
pub use init_protocol_fees_vault::*;
pub use init_validator_fees_vault::*;
pub use protocol_claim_fees::*;
Expand Down
6 changes: 6 additions & 0 deletions src/discriminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ pub enum DlpDiscriminator {

/// See [crate::processor::process_delegate_with_actions] for docs.
DelegateWithActions = 23,

/// See [crate::processor::process_init_magic_fee_vault] for docs.
InitMagicFeeVault = 24,

/// See [crate::processor::process_delegate_magic_fee_vault] for docs.
DelegateMagicFeeVault = 25,
}

impl DlpDiscriminator {
Expand Down
8 changes: 8 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ pub fn slow_process_instruction(
.or(Err(ProgramError::InvalidInstructionData))?;

match ix {
DlpDiscriminator::InitMagicFeeVault => {
processor::process_init_magic_fee_vault(program_id, accounts, data)?
}
DlpDiscriminator::InitValidatorFeesVault => {
processor::process_init_validator_fees_vault(
program_id, accounts, data,
Expand Down Expand Up @@ -200,6 +203,11 @@ pub fn slow_process_instruction(
program_id, accounts, data,
)?
}
DlpDiscriminator::DelegateMagicFeeVault => {
processor::process_delegate_magic_fee_vault(
program_id, accounts, data,
)?
}
DlpDiscriminator::CloseEphemeralBalance => {
processor::process_close_ephemeral_balance(
program_id, accounts, data,
Expand Down
16 changes: 16 additions & 0 deletions src/pda.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,22 @@ macro_rules! program_config_seeds_from_program_id {
};
}

pub const MAGIC_FEE_VAULT_TAG: &[u8] = b"magic-fee-vault";
#[macro_export]
macro_rules! magic_fee_vault_seeds_from_validator {
($validator: expr) => {
&[$crate::pda::MAGIC_FEE_VAULT_TAG, &$validator.as_ref()]
};
}

pub fn magic_fee_vault_pda_from_validator(validator: &Pubkey) -> Pubkey {
Pubkey::find_program_address(
magic_fee_vault_seeds_from_validator!(validator),
&crate::id(),
)
.0
}

pub const EPHEMERAL_BALANCE_TAG: &[u8] = b"balance";
#[macro_export]
macro_rules! ephemeral_balance_seeds_from_payer {
Expand Down
132 changes: 132 additions & 0 deletions src/processor/delegate_magic_fee_vault.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
use solana_program::{
account_info::AccountInfo,
entrypoint::ProgramResult,
instruction::{AccountMeta, Instruction},
msg,
program::invoke_signed,
program_error::ProgramError,
pubkey::Pubkey,
system_program,
};

use crate::{
args::DelegateArgs,
discriminator::DlpDiscriminator,
magic_fee_vault_seeds_from_validator,
pda::magic_fee_vault_pda_from_validator,
processor::utils::loaders::{
load_initialized_pda, load_initialized_validator_fees_vault,
load_program, load_signer,
},
};

/// Delegates the magic fee vault PDA for a validator.
///
/// Accounts:
///
/// 0: `[writable, signer]` payer
/// 1: `[signer]` validator identity
/// 2: `[]` validator fees vault (proves validator is registered)
/// 3: `[writable]` magic fee vault PDA
/// 4: `[writable]` delegate buffer PDA
/// 5: `[writable]` delegation record PDA
/// 6: `[writable]` delegation metadata PDA
/// 7: `[]` system program
/// 8: `[]` this program
///
/// Requirements:
///
/// - payer must be a signer
/// - validator must be a signer and registered (has a validator fees vault)
/// - magic fee vault must be the PDA derived from this validator and be initialized
/// - delegation record must be uninitialized
pub fn process_delegate_magic_fee_vault(
_program_id: &Pubkey,
accounts: &[AccountInfo],
_data: &[u8],
) -> ProgramResult {
let [payer, validator, validator_fees_vault, magic_fee_vault, delegate_buffer, delegation_record, delegation_metadata, system_program, delegation_program] =
accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};

load_signer(payer, "payer")?;
load_signer(validator, "validator")?;
load_program(system_program, system_program::id(), "system program")?;
load_program(delegation_program, crate::id(), "delegation program")?;

// Verify validator is registered
load_initialized_validator_fees_vault(
validator,
validator_fees_vault,
false,
)?;

// Verify the magic fee vault is indeed derived from this validator
let expected_vault = magic_fee_vault_pda_from_validator(validator.key);
if !expected_vault.eq(magic_fee_vault.key) {
msg!(
"Magic fee vault {} is not derived from validator {}",
magic_fee_vault.key,
validator.key
);
return Err(ProgramError::InvalidAccountData);
}

// Verify magic fee vault is initialized (owned by this program)
let magic_fee_vault_bump = load_initialized_pda(
magic_fee_vault,
magic_fee_vault_seeds_from_validator!(validator.key),
&crate::id(),
true,
"magic fee vault",
)?;

let magic_fee_vault_seeds: &[&[u8]] =
magic_fee_vault_seeds_from_validator!(validator.key);

let delegate_args = DelegateArgs {
commit_frequency_ms: 0,
seeds: magic_fee_vault_seeds.iter().map(|s| s.to_vec()).collect(),
validator: Some(*validator.key),
};

let mut data = DlpDiscriminator::Delegate.to_vec();
data.extend(borsh::to_vec(&delegate_args)?);

// Create delegation ix
let ix = Instruction {
program_id: crate::id(),
accounts: vec![
AccountMeta::new(*payer.key, true),
AccountMeta::new(*magic_fee_vault.key, true),
AccountMeta::new_readonly(crate::id(), false),
AccountMeta::new(*delegate_buffer.key, false),
AccountMeta::new(*delegation_record.key, false),
AccountMeta::new(*delegation_metadata.key, false),
AccountMeta::new_readonly(system_program::id(), false),
],
data,
};

let magic_fee_vault_bump_slice = &[magic_fee_vault_bump];
let magic_fee_vault_signer_seeds =
[magic_fee_vault_seeds, &[magic_fee_vault_bump_slice]].concat();

invoke_signed(
&ix,
&[
delegation_program.clone(),
payer.clone(),
magic_fee_vault.clone(),
delegate_buffer.clone(),
delegation_record.clone(),
delegation_metadata.clone(),
system_program.clone(),
],
&[&magic_fee_vault_signer_seeds],
)?;

Ok(())
}
75 changes: 75 additions & 0 deletions src/processor/init_magic_fee_vault.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use solana_program::{
account_info::AccountInfo, entrypoint::ProgramResult,
program_error::ProgramError, pubkey::Pubkey, system_program,
};

use crate::{
magic_fee_vault_seeds_from_validator,
processor::utils::{
loaders::{
load_initialized_validator_fees_vault, load_program, load_signer,
load_uninitialized_pda,
},
pda::create_pda,
},
};

/// Process the initialization of the magic fee vault
///
/// Accounts:
///
/// 0; `[signer, writable]` payer
/// 1; `[signer]` validator_identity
/// 2; `[]` validator_fees_vault
/// 3; `[writable]` magic_fee_vault
/// 4; `[]` system_program
///
/// Requirements:
///
/// - validator must be a signer
/// - validator must have an initialized validator fees vault (i.e. be whitelisted)
/// - magic fee vault PDA must not be already initialized
///
/// 1. Verify validator is signer and whitelisted
/// 2. Create the magic fee vault PDA (not delegated)
pub fn process_init_magic_fee_vault(
_program_id: &Pubkey,
accounts: &[AccountInfo],
_data: &[u8],
) -> ProgramResult {
let [payer, validator, validator_fees_vault, magic_fee_vault, system_program] =
accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};

load_signer(payer, "payer")?;
load_signer(validator, "validator")?;
load_program(system_program, system_program::id(), "system program")?;

load_initialized_validator_fees_vault(
validator,
validator_fees_vault,
false,
)?;

let magic_fee_vault_bump = load_uninitialized_pda(
magic_fee_vault,
magic_fee_vault_seeds_from_validator!(validator.key),
&crate::id(),
true,
"magic fee vault",
)?;

create_pda(
magic_fee_vault,
&crate::id(),
8,
magic_fee_vault_seeds_from_validator!(validator.key),
magic_fee_vault_bump,
system_program,
payer,
)?;

Ok(())
}
4 changes: 4 additions & 0 deletions src/processor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ mod call_handler_v2;
mod close_ephemeral_balance;
mod close_validator_fees_vault;
mod delegate_ephemeral_balance;
mod delegate_magic_fee_vault;
mod init_magic_fee_vault;
mod init_protocol_fees_vault;
mod init_validator_fees_vault;
mod protocol_claim_fees;
Expand All @@ -18,6 +20,8 @@ pub use call_handler_v2::*;
pub use close_ephemeral_balance::*;
pub use close_validator_fees_vault::*;
pub use delegate_ephemeral_balance::*;
pub use delegate_magic_fee_vault::*;
pub use init_magic_fee_vault::*;
pub use init_protocol_fees_vault::*;
pub use init_validator_fees_vault::*;
pub use protocol_claim_fees::*;
Expand Down
Loading
Loading