Skip to main content
added 181 characters in body
Source Link
Burger Bob
  • 1.5k
  • 4
  • 19

This is what I came up with:

Setup

pub enum VaultLabel {
    None,
    Treasury,
    Community,
    Operations,
}

#[account]
pub struct Vault {
    pub bump: u8,
    pub pct: u8,
    pub label: VaultLabel,
}

Then I create an instruction context that initialises all the required vaults. Each vault just becomes a global PDA with a predefined seed, where the PDA can own some token accounts:

pub struct VaultCreate<'info> {
    #[account(
        init,
        seeds = [SEED_TREASURY],
        bump,
        payer = payer,
        space = Vault::LEN,
    )]
    pub treasury: Account<'info, Vault>,

    #[account(
        init,
        seeds = [SEED_COMMUNITY],
        bump,
        payer = payer,
        space = Vault::LEN,
    )]
    pub community: Account<'info, Vault>,

    ...
}

pub struct VaultCreateParams {
    pub percentages: {treasury: u8, community: u8, operations: u8},
}

Note

  • payer can be restricted to be an admin of a specific pubkey.
  • All the vaults are initialized AT ONCE, since this ensures you can maintain a maximum distribution percentage of 100%. So you would check that VaultCreateParams add up to precisely 100.
  • Using PDAs to maintain the vaults since this is likely more secure than regular wallet System Accounts

Distribution logic

If you have an instruction for payment, you could incorporate the distribution logic therein (of course, this depends on your particular use-case)

  1. Pass in the vaults in addition to their token accounts as remaining_accounts. Deserialize with Account::<'info, Vault> and Account::<'info, TokenAccount>::try_from. Combining with address lookup tables and versioned transactions, the extra account overhead is negligible, especially when those accounts remain constant
  2. Check that the vault address PDA is the right pubkey
  3. Check that the vault owns the vault token account
  4. Do token transfers according to the vault.pct
  5. Check that each distribution endpoint has been processed exactly once. I.e. in a for loop you would have to check if it has looped through the expected vault.labels or accounts

This is what I came up with:

Setup

pub enum VaultLabel {
    None,
    Treasury,
    Community,
    Operations,
}

#[account]
pub struct Vault {
    pub bump: u8,
    pub pct: u8,
    pub label: VaultLabel,
}

Then I create an instruction context that initialises all the required vaults. Each vault just becomes a global PDA with a predefined seed, where the PDA can own some token accounts:

pub struct VaultCreate<'info> {
    #[account(
        init,
        seeds = [SEED_TREASURY],
        bump,
        payer = payer,
        space = Vault::LEN,
    )]
    pub treasury: Account<'info, Vault>,

    #[account(
        init,
        seeds = [SEED_COMMUNITY],
        bump,
        payer = payer,
        space = Vault::LEN,
    )]
    pub community: Account<'info, Vault>,

    ...
}

pub struct VaultCreateParams {
    pub percentages: {treasury: u8, community: u8, operations: u8},
}

Note

  • payer can be restricted to be an admin of a specific pubkey.
  • All the vaults are initialized AT ONCE, since this ensures you can maintain a maximum distribution percentage of 100%. So you would check that VaultCreateParams add up to precisely 100.
  • Using PDAs to maintain the vaults since this is likely more secure than regular wallet System Accounts

Distribution logic

If you have an instruction for payment, you could incorporate the distribution logic therein (of course, this depends on your particular use-case)

  1. Pass in the vaults in addition to their token accounts as remaining_accounts. Deserialize with Account::<'info, Vault> and Account::<'info, TokenAccount>::try_from. Combining with address lookup tables and versioned transactions, the extra account overhead is negligible, especially when those accounts remain constant
  2. Check that the vault address PDA is the right pubkey
  3. Check that the vault owns the vault token account
  4. Do token transfers according to the vault.pct

This is what I came up with:

Setup

pub enum VaultLabel {
    None,
    Treasury,
    Community,
    Operations,
}

#[account]
pub struct Vault {
    pub bump: u8,
    pub pct: u8,
    pub label: VaultLabel,
}

Then I create an instruction context that initialises all the required vaults. Each vault just becomes a global PDA with a predefined seed, where the PDA can own some token accounts:

pub struct VaultCreate<'info> {
    #[account(
        init,
        seeds = [SEED_TREASURY],
        bump,
        payer = payer,
        space = Vault::LEN,
    )]
    pub treasury: Account<'info, Vault>,

    #[account(
        init,
        seeds = [SEED_COMMUNITY],
        bump,
        payer = payer,
        space = Vault::LEN,
    )]
    pub community: Account<'info, Vault>,

    ...
}

pub struct VaultCreateParams {
    pub percentages: {treasury: u8, community: u8, operations: u8},
}

Note

  • payer can be restricted to be an admin of a specific pubkey.
  • All the vaults are initialized AT ONCE, since this ensures you can maintain a maximum distribution percentage of 100%. So you would check that VaultCreateParams add up to precisely 100.
  • Using PDAs to maintain the vaults since this is likely more secure than regular wallet System Accounts

Distribution logic

If you have an instruction for payment, you could incorporate the distribution logic therein (of course, this depends on your particular use-case)

  1. Pass in the vaults in addition to their token accounts as remaining_accounts. Deserialize with Account::<'info, Vault> and Account::<'info, TokenAccount>::try_from. Combining with address lookup tables and versioned transactions, the extra account overhead is negligible, especially when those accounts remain constant
  2. Check that the vault address PDA is the right pubkey
  3. Check that the vault owns the vault token account
  4. Do token transfers according to the vault.pct
  5. Check that each distribution endpoint has been processed exactly once. I.e. in a for loop you would have to check if it has looped through the expected vault.labels or accounts
added 150 characters in body
Source Link
Burger Bob
  • 1.5k
  • 4
  • 19

This is what I came up with:

Setup

pub enum VaultLabel {
    None,
    Treasury,
    Community,
    Operations,
}

#[account]
pub struct Vault {
    pub bump: u8,
    pub pct: u8,
    pub label: VaultLabel,
}

Then I create an instruction context that initialises all the required vaults. Each vault just becomes a global PDA with a predefined seed, where the PDA can own some token accounts:

pub struct VaultCreate<'info> {
    #[account(
        init,
        seeds = [SEED_TREASURY],
        bump,
        payer = payer,
        space = Vault::LEN,
    )]
    pub treasury: Account<'info, Vault>,

    #[account(
        init,
        seeds = [SEED_COMMUNITY],
        bump,
        payer = payer,
        space = Vault::LEN,
    )]
    pub community: Account<'info, Vault>,

    ...
}

pub struct VaultCreateParams {
    pub percentages: {treasury: u8, community: u8, operations: u8},
}

Note

  • payer can be restricted to be an admin of a specific pubkey.
  • All the vaults are initialized AT ONCE, since this ensures you can maintain a maximum distribution percentage of 100%. So you would check that VaultCreateParams add up to precisely 100.
  • Using PDAs to maintain the vaults since this is likely more secure than regular wallet System Accounts

Distribution logic

If you have an instruction for payment, you could incorporate the distribution logic therein (of course, this depends on your particular use-case)

  1. Pass in the vaults in addition to their token accounts as remaining_accounts. Deserialize with Account::<'info, Vault> and Account::<'info, TokenAccount>::try_from. Combining with address lookup tables and versioned transactions, the extra account overhead is negligible, especially when those accounts remain constant
  2. Check that the vault address PDA is the right pubkey
  3. Check that the vault owns the vault token account
  4. Do token transfers according to the vault.pct

This is what I came up with:

Setup

pub enum VaultLabel {
    None,
    Treasury,
    Community,
    Operations,
}

#[account]
pub struct Vault {
    pub bump: u8,
    pub pct: u8,
    pub label: VaultLabel,
}

Then I create an instruction context that initialises all the required vaults. Each vault just becomes a global PDA with a predefined seed, where the PDA can own some token accounts:

pub struct VaultCreate<'info> {
    #[account(
        init,
        seeds = [SEED_TREASURY],
        bump,
        payer = payer,
        space = Vault::LEN,
    )]
    pub treasury: Account<'info, Vault>,

    #[account(
        init,
        seeds = [SEED_COMMUNITY],
        bump,
        payer = payer,
        space = Vault::LEN,
    )]
    pub community: Account<'info, Vault>,

    ...
}

pub struct VaultCreateParams {
    pub percentages: {treasury: u8, community: u8, operations: u8},
}

Note

  • payer can be restricted to be an admin of a specific pubkey.
  • All the vaults are initialized AT ONCE, since this ensures you can maintain a maximum distribution percentage of 100%. So you would check that VaultCreateParams add up to precisely 100.
  • Using PDAs to maintain the vaults since this is likely more secure than regular wallet System Accounts

Distribution logic

  1. Pass in the vaults in addition to their token accounts as remaining_accounts. Deserialize with Account::<'info, Vault> and Account::<'info, TokenAccount>::try_from. Combining with address lookup tables and versioned transactions, the extra account overhead is negligible, especially when those accounts remain constant
  2. Check that the vault address PDA is the right pubkey
  3. Check that the vault owns the vault token account
  4. Do token transfers according to the vault.pct

This is what I came up with:

Setup

pub enum VaultLabel {
    None,
    Treasury,
    Community,
    Operations,
}

#[account]
pub struct Vault {
    pub bump: u8,
    pub pct: u8,
    pub label: VaultLabel,
}

Then I create an instruction context that initialises all the required vaults. Each vault just becomes a global PDA with a predefined seed, where the PDA can own some token accounts:

pub struct VaultCreate<'info> {
    #[account(
        init,
        seeds = [SEED_TREASURY],
        bump,
        payer = payer,
        space = Vault::LEN,
    )]
    pub treasury: Account<'info, Vault>,

    #[account(
        init,
        seeds = [SEED_COMMUNITY],
        bump,
        payer = payer,
        space = Vault::LEN,
    )]
    pub community: Account<'info, Vault>,

    ...
}

pub struct VaultCreateParams {
    pub percentages: {treasury: u8, community: u8, operations: u8},
}

Note

  • payer can be restricted to be an admin of a specific pubkey.
  • All the vaults are initialized AT ONCE, since this ensures you can maintain a maximum distribution percentage of 100%. So you would check that VaultCreateParams add up to precisely 100.
  • Using PDAs to maintain the vaults since this is likely more secure than regular wallet System Accounts

Distribution logic

If you have an instruction for payment, you could incorporate the distribution logic therein (of course, this depends on your particular use-case)

  1. Pass in the vaults in addition to their token accounts as remaining_accounts. Deserialize with Account::<'info, Vault> and Account::<'info, TokenAccount>::try_from. Combining with address lookup tables and versioned transactions, the extra account overhead is negligible, especially when those accounts remain constant
  2. Check that the vault address PDA is the right pubkey
  3. Check that the vault owns the vault token account
  4. Do token transfers according to the vault.pct
Source Link
Burger Bob
  • 1.5k
  • 4
  • 19

This is what I came up with:

Setup

pub enum VaultLabel {
    None,
    Treasury,
    Community,
    Operations,
}

#[account]
pub struct Vault {
    pub bump: u8,
    pub pct: u8,
    pub label: VaultLabel,
}

Then I create an instruction context that initialises all the required vaults. Each vault just becomes a global PDA with a predefined seed, where the PDA can own some token accounts:

pub struct VaultCreate<'info> {
    #[account(
        init,
        seeds = [SEED_TREASURY],
        bump,
        payer = payer,
        space = Vault::LEN,
    )]
    pub treasury: Account<'info, Vault>,

    #[account(
        init,
        seeds = [SEED_COMMUNITY],
        bump,
        payer = payer,
        space = Vault::LEN,
    )]
    pub community: Account<'info, Vault>,

    ...
}

pub struct VaultCreateParams {
    pub percentages: {treasury: u8, community: u8, operations: u8},
}

Note

  • payer can be restricted to be an admin of a specific pubkey.
  • All the vaults are initialized AT ONCE, since this ensures you can maintain a maximum distribution percentage of 100%. So you would check that VaultCreateParams add up to precisely 100.
  • Using PDAs to maintain the vaults since this is likely more secure than regular wallet System Accounts

Distribution logic

  1. Pass in the vaults in addition to their token accounts as remaining_accounts. Deserialize with Account::<'info, Vault> and Account::<'info, TokenAccount>::try_from. Combining with address lookup tables and versioned transactions, the extra account overhead is negligible, especially when those accounts remain constant
  2. Check that the vault address PDA is the right pubkey
  3. Check that the vault owns the vault token account
  4. Do token transfers according to the vault.pct