Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LockerV3: add batch vesting escrow lock creation #25

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
8a16c92
v3: batch vesting escrow
docongminh Jan 9, 2025
f883eab
merkle tree
docongminh Jan 9, 2025
0bcec0e
unittest for batch vesting escrow
docongminh Jan 9, 2025
55074e7
add close escrow vesting
docongminh Jan 9, 2025
a71b6e1
assertion validate claim status state
docongminh Jan 9, 2025
bd5374c
use safe math
docongminh Jan 10, 2025
dea637f
add cancel_mode
docongminh Jan 10, 2025
d4dc50b
update build node
docongminh Jan 10, 2025
01eede9
payer create claim status
docongminh Jan 10, 2025
3edc422
add creator cancel escrow
docongminh Jan 10, 2025
61c4ac3
update node for root
docongminh Jan 10, 2025
4cd0f8f
update node for root
docongminh Jan 10, 2025
d60910f
update unit test
docongminh Jan 10, 2025
57469a1
fix be_bytes()
docongminh Jan 10, 2025
53a51ca
add vestingStartTime to node
docongminh Jan 10, 2025
877358c
remove init if needed
docongminh Jan 10, 2025
752672f
remove init if needed
docongminh Jan 10, 2025
28fe042
add validate node data
docongminh Jan 10, 2025
e4a0eac
clean code
docongminh Jan 10, 2025
7001eba
removed mutable for unnecessary
docongminh Jan 11, 2025
1b64a24
uncheck token account
docongminh Jan 11, 2025
3a7e075
immutable signer
docongminh Jan 11, 2025
c11ab0b
add more testcase
docongminh Jan 11, 2025
8d123f3
clean coding convention
docongminh Jan 11, 2025
bdbafeb
add buffer for claim_status
docongminh Jan 11, 2025
d018d7f
add padding fields
docongminh Jan 11, 2025
27fddb4
set recipient email is empty
docongminh Jan 11, 2025
d32641b
add close claim status instruction
docongminh Jan 11, 2025
4969c1b
rename variable
docongminh Jan 11, 2025
ef05e8d
validate node data
docongminh Jan 12, 2025
96b4ee8
add rent_receiver
docongminh Jan 13, 2025
dc31f66
add comment
docongminh Jan 13, 2025
dda602f
remove close escrow instruction
docongminh Jan 14, 2025
627b234
update logic fill claim status data
docongminh Jan 19, 2025
1e7d01e
use recipient endpoint for v1 v2
docongminh Jan 19, 2025
a11684e
remove create metadata v3
docongminh Jan 20, 2025
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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ incremental = false
codegen-units = 1

[workspace.dependencies]
anchor-lang = "0.30.1"
anchor-lang = { version = "0.30.1", features = ["init-if-needed"] }
anchor-spl = "0.30.1"
anchor-client = "0.30.1"
clap = { version = "3.2.25", features = ["derive", "env"] }
Expand Down
3 changes: 3 additions & 0 deletions programs/locker/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,7 @@ pub enum LockerError {

#[msg("Claiming is not finished")]
ClaimingIsNotFinished,

#[msg("Invalid merkle proof")]
InvalidMerkleProof,
}
30 changes: 30 additions & 0 deletions programs/locker/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,35 @@ pub struct EventCreateVestingEscrow {
pub escrow: Pubkey,
}

#[event]
pub struct EventCreateVestingEscrowV3 {
pub total_deposit_amount: u64,
pub escrow: Pubkey,
pub cancel_mode: u8,
pub root: [u8; 32],
}

#[event]
pub struct EventClaim {
pub amount: u64,
pub current_ts: u64,
pub escrow: Pubkey,
}

#[event]
pub struct EventClaimV3 {
pub amount: u64,
pub current_ts: u64,
pub escrow: Pubkey,
pub vesting_start_time: u64,
pub cliff_time: u64,
pub frequency: u64,
pub cliff_unlock_amount: u64,
pub amount_per_period: u64,
pub number_of_period: u64,
pub recipient: Pubkey
}

#[event]
pub struct EventUpdateVestingEscrowRecipient {
pub escrow: Pubkey,
Expand All @@ -38,6 +60,14 @@ pub struct EventCancelVestingEscrow {
pub cancelled_at: u64,
}

#[event]
pub struct EventCancelVestingEscrowV3 {
pub escrow: Pubkey,
pub signer: Pubkey,
pub remaining_amount: u64,
pub cancelled_at: u64,
}

#[event]
pub struct EventCloseVestingEscrow {
pub escrow: Pubkey,
Expand Down
2 changes: 2 additions & 0 deletions programs/locker/src/instructions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ pub mod v2;
pub use v2::*;
pub mod close_vesting_escrow;
pub use close_vesting_escrow::*;
pub mod v3;
pub use v3::*;
130 changes: 130 additions & 0 deletions programs/locker/src/instructions/v3/cancel_vesting_escrow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
use crate::util::MemoTransferContext;
use crate::*;
use anchor_spl::memo::Memo;
use anchor_spl::token_interface::{
close_account, CloseAccount, Mint, TokenAccount, TokenInterface,
};
use util::{
harvest_fees, parse_remaining_accounts, transfer_to_user_v3, AccountsType,
ParsedRemainingAccounts, TRANSFER_MEMO_CANCEL_VESTING,
};

/// Accounts for [locker::cancel_vesting_escrow_v3].
#[derive(Accounts)]
#[event_cpi]
pub struct CancelVestingEscrowV3<'info> {
/// Escrow.
#[account(
mut,
has_one = token_mint,
constraint = escrow.load()?.cancelled_at == 0 @ LockerError::AlreadyCancelled
)]
pub escrow: AccountLoader<'info, VestingEscrowV3>,

/// Mint.
#[account(mut)]
andrewsource147 marked this conversation as resolved.
Show resolved Hide resolved
pub token_mint: Box<InterfaceAccount<'info, Mint>>,

/// Escrow Token Account.
#[account(
mut,
associated_token::mint = token_mint,
associated_token::authority = escrow,
associated_token::token_program = token_program
)]
pub escrow_token: Box<InterfaceAccount<'info, TokenAccount>>,

/// Creator Token Account.
#[account(mut)]
pub creator_token: Box<InterfaceAccount<'info, TokenAccount>>,
andrewsource147 marked this conversation as resolved.
Show resolved Hide resolved

/// CHECKED: The Token Account will receive the rent
#[account(mut)]
pub rent_receiver: UncheckedAccount<'info>,

/// Signer.
pub signer: Signer<'info>,

/// Memo program.
pub memo_program: Program<'info, Memo>,

/// Token program.
pub token_program: Interface<'info, TokenInterface>,
}

impl<'info> CancelVestingEscrowV3<'info> {
fn close_escrow_token_v3(&self) -> Result<()> {
let escrow = self.escrow.load()?;
let escrow_seeds = escrow_seeds_v3!(escrow);

close_account(CpiContext::new_with_signer(
self.token_program.to_account_info(),
CloseAccount {
account: self.escrow_token.to_account_info(),
destination: self.rent_receiver.to_account_info(),
authority: self.escrow.to_account_info(),
},
&[&escrow_seeds[..]],
))?;

Ok(())
}
}

pub fn handle_cancel_vesting_escrow_v3<'c: 'info, 'info>(
ctx: Context<'_, '_, 'c, 'info, CancelVestingEscrowV3<'info>>,
remaining_accounts_info: Option<RemainingAccountsInfo>,
) -> Result<()> {
let mut escrow = ctx.accounts.escrow.load_mut()?;
let signer = ctx.accounts.signer.key();
escrow.validate_cancel_actor(signer)?;
andrewsource147 marked this conversation as resolved.
Show resolved Hide resolved

let current_ts = Clock::get()?.unix_timestamp as u64;
let remaining_amount = ctx.accounts.escrow_token.amount;
escrow.cancelled_at = current_ts;
require!(escrow.cancelled_at > 0, LockerError::CancelledAtIsZero);
drop(escrow);

// Process remaining accounts
let mut remaining_accounts = &ctx.remaining_accounts[..];
let parsed_transfer_hook_accounts = match remaining_accounts_info {
Some(info) => parse_remaining_accounts(
&mut remaining_accounts,
&info.slices,
&[AccountsType::TransferHookEscrow],
)?,
None => ParsedRemainingAccounts::default(),
};

// Transfer the remaining amount to the creator
transfer_to_user_v3(
&ctx.accounts.escrow,
&ctx.accounts.token_mint,
&ctx.accounts.escrow_token.to_account_info(),
&ctx.accounts.creator_token,
&ctx.accounts.token_program,
Some(MemoTransferContext {
memo_program: &ctx.accounts.memo_program,
memo: TRANSFER_MEMO_CANCEL_VESTING.as_bytes(),
}),
remaining_amount,
parsed_transfer_hook_accounts.transfer_hook_escrow,
)?;

// Do fee harvesting
harvest_fees(
&ctx.accounts.token_program,
&ctx.accounts.escrow_token.to_account_info(),
&ctx.accounts.token_mint,
)?;

ctx.accounts.close_escrow_token_v3()?;

emit_cpi!(EventCancelVestingEscrowV3 {
escrow: ctx.accounts.escrow.key(),
signer,
remaining_amount,
cancelled_at: current_ts,
});
Ok(())
}
Loading