Skip to content

Conversation

@defi0x1
Copy link
Collaborator

@defi0x1 defi0x1 commented Jan 22, 2025

Flow for storage a part of proof onchain:

  1. Operator create a distributor root
  2. Operator create distributors
  3. Operator create canopy tree for each distributor.
  4. Admin fund to distributor root
  5. Permissionless: fund distributor from distributor root.

Note:
I quickly tested the NewClaimAndStake transaction locally using:

  • depth: 2
  • proof length: 2

The resulting transaction size was 661 bytes. That means we have about 571 bytes of remaining space, which should accommodate roughly 17 proofs for this transaction in this case.

@defi0x1 defi0x1 changed the title [draft] Add partial merkle tree Storage subset merkle tree onchain Jan 23, 2025
pub struct DistributeVault<'info> {
/// The [ParentState].
#[account(has_one = admin)]
pub parent_account: AccountLoader<'info, ParentAccount>,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DisitributorRoot

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated


/// Accounts required for distributing tokens from the parent vault to distributor vaults.
#[derive(Accounts)]
pub struct DistributeVault<'info> {
Copy link

@andrewsource147 andrewsource147 Feb 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FundMerkleDisitributorFromRoot

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

#[derive(Accounts)]
pub struct DistributeVault<'info> {
/// The [ParentState].
#[account(has_one = admin)]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

permissionless?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

pub parent_vault: Account<'info, TokenAccount>,

/// Admin
pub admin: Signer<'info>,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need admin here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

// [distributor_vault, distributor, distributor_vault, distributor]
let remaining_accounts: &[AccountInfo] = ctx.remaining_accounts;
// Ensure valid layout.
if remaining_accounts.len() % 2 != 0 {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need remaninings accounts here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

);

// Check distributor has been funded token
if distributor_vault.amount >= distributor_state.max_total_claim {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

distributor_state.funded_amount

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

pub root: [u8; 32],
pub total_nodes: u8,
pub depth: u8,
pub nodes: Vec<[u8; 32]>,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

push in last account

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

pub version: u64,
pub root: [u8; 32],
pub total_nodes: u8,
pub depth: u8,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you test max depth

space = 8 + MerkleDistributor::INIT_SPACE,
payer = admin
)]
pub distributor: AccountLoader<'info, MerkleDistributor>,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use init_if_needed for token_vault

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

pub partial_merkle_tree: Account<'info, PartialMerkleTree>,

/// Base key of the distributor.
pub base: Signer<'info>,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use admin as unchecked_account, and payer to pay for rent

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

space = PartialMerkleTree::space(total_node as usize),
payer = admin
)]
pub partial_merkle_tree: Account<'info, PartialMerkleTree>,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

save nodes in distributor state

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because AccountLoader does not support storing a dynamic Vec directly. So, create CanopyTree to storage metadata (root, nodes, depth..) of MerkleDistributor

pub claim_type: u8,
pub operator: Pubkey,
pub locker: Pubkey,
pub parent_account: Pubkey,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parent should be pda of base + mint

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

init,
seeds = [
b"ParentAccount".as_ref(),
mint.key().to_bytes().as_ref(),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pda of mint and base

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto^

/// Parent vault
/// Should create previously
#[account(
associated_token::mint = mint,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

init if need

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

pub system_program: Program<'info, System>,
}

pub fn handle_new_parent_account(ctx: Context<NewParentAccount>) -> Result<()> {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

max amount claim and max node

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

use anchor_spl::token::{Mint, TokenAccount};

#[derive(Accounts)]
pub struct NewParentAccount<'info> {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a function to transfer fund to parent account

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done with FundDistributorRoot

let mut parent_account = ctx.accounts.parent_account.load_init()?;

parent_account.bump = *ctx.bumps.get("parent_account").unwrap();
parent_account.admin = ctx.accounts.admin.key();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we dont need parent account

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

partial_merkle_tree.depth,
initial_index,
proof,
partial_merkle_tree.nodes.clone(),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should use &partial_merkle_tree.nodes.clone()

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

/// Token Address of parent vault
pub parent_vault: Pubkey,
/// Padding
pub padding: u64,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need padding here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants