Fair launch update to anchor 14 and finish fleshing out commands

This commit is contained in:
Jordan Prince 2021-09-04 18:40:27 -05:00
parent a6e4b02a74
commit 71ece1b8bb
2 changed files with 108 additions and 8 deletions

View File

@ -15,6 +15,7 @@ cpi = ["no-entrypoint"]
default = [] default = []
[dependencies] [dependencies]
anchor-lang = "0.13.2" anchor-lang = "0.14.0"
anchor-spl = "0.14.0"
arrayref = "0.3.6" arrayref = "0.3.6"
spl-token = { version="3.1.1", features = [ "no-entrypoint" ] } spl-token = { version="3.1.1", features = [ "no-entrypoint" ] }

View File

@ -7,12 +7,14 @@ use {
solana_program::{clock::UnixTimestamp, program_pack::Pack, system_program}, solana_program::{clock::UnixTimestamp, program_pack::Pack, system_program},
AnchorDeserialize, AnchorSerialize, AnchorDeserialize, AnchorSerialize,
}, },
anchor_spl::token::{self, TokenAccount},
spl_token::state::{Account, Mint}, spl_token::state::{Account, Mint},
}; };
pub const PREFIX: &str = "fair_launch"; pub const PREFIX: &str = "fair_launch";
pub const TREASURY: &str = "treasury"; pub const TREASURY: &str = "treasury";
pub const MINT: &str = "mint"; pub const MINT: &str = "mint";
pub const LOTTERY: &str="lottery";
#[program] #[program]
pub mod fair_launch { pub mod fair_launch {
@ -42,6 +44,7 @@ pub struct InitializeFairLaunch<'info> {
rent: Sysvar<'info, Rent>, rent: Sysvar<'info, Rent>,
} }
/// Can only update fair launch before phase 1 start.
#[derive(Accounts)] #[derive(Accounts)]
pub struct UpdateFairLaunch<'info> { pub struct UpdateFairLaunch<'info> {
#[account(mut, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), &[fair_launch.bump]], has_one=authority)] #[account(mut, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), &[fair_launch.bump]], has_one=authority)]
@ -50,6 +53,44 @@ pub struct UpdateFairLaunch<'info> {
authority: AccountInfo<'info>, authority: AccountInfo<'info>,
} }
/// Limited Update that only sets phase 3 dates once bitmap is in place.
#[derive(Accounts)]
pub struct StartPhaseThree<'info> {
#[account(mut, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), &[fair_launch.bump]], has_one=authority)]
fair_launch: ProgramAccount<'info, FairLaunch>,
#[account(signer)]
authority: AccountInfo<'info>,
}
/// Can only create the fair launch lottery bitmap after phase 1 has ended.
#[derive(Accounts)]
#[instruction(bump: u8)]
pub struct CreateFairLaunchLotteryBitmap<'info> {
#[account(seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), &[fair_launch.bump]], has_one=authority)]
fair_launch: ProgramAccount<'info, FairLaunch>,
#[account(init, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), LOTTERY.as_bytes()], payer=payer, bump=bump, space= FAIR_LAUNCH_LOTTERY_SIZE + (fair_launch.number_tickets_sold_in_phase_1.checked_div(8).ok_or(ErrorCode::NumericalOverflowError)? as usize) + 1)]
fair_launch_lottery_bitmap: ProgramAccount<'info, FairLaunchLotteryBitmap>,
#[account(signer)]
authority: AccountInfo<'info>,
#[account(mut, signer)]
payer: AccountInfo<'info>,
#[account(address = system_program::ID)]
system_program: AccountInfo<'info>,
rent: Sysvar<'info, Rent>,
}
/// Can only set the fair launch lottery bitmap after phase 2 has ended.
#[derive(Accounts)]
pub struct UpdateFairLaunchLotteryBitmap<'info> {
#[account(seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), &[fair_launch.bump]], has_one=authority)]
fair_launch: ProgramAccount<'info, FairLaunch>,
#[account(mut, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), LOTTERY.as_bytes(), &[fair_launch_lottery_bitmap.bump]])]
fair_launch_lottery_bitmap: ProgramAccount<'info, FairLaunchLotteryBitmap>,
#[account(signer)]
authority: AccountInfo<'info>,
}
/// Can only purchase a ticket in phase 1.
#[derive(Accounts)] #[derive(Accounts)]
#[instruction(bump: u8, amount: u64)] #[instruction(bump: u8, amount: u64)]
pub struct PurchaseTicket<'info> { pub struct PurchaseTicket<'info> {
@ -59,6 +100,8 @@ pub struct PurchaseTicket<'info> {
treasury: AccountInfo<'info>, treasury: AccountInfo<'info>,
#[account(init, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), buyer.key.as_ref()], payer=payer, bump=bump, space=FAIR_LAUNCH_TICKET_SIZE)] #[account(init, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), buyer.key.as_ref()], payer=payer, bump=bump, space=FAIR_LAUNCH_TICKET_SIZE)]
fair_launch_ticket: ProgramAccount<'info, FairLaunchTicket>, fair_launch_ticket: ProgramAccount<'info, FairLaunchTicket>,
#[account(init, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), &fair_launch.number_tickets_sold_in_phase_1.to_le_bytes()], payer=payer, bump=bump, space=FAIR_LAUNCH_TICKET_SEQ_SIZE)]
fair_launch_ticket_seq_lookup: ProgramAccount<'info, FairLaunchTicket>,
#[account(mut, signer, constraint= (treasury.owner == &spl_token::id() && buyer.owner == &spl_token::id()) || (treasury.owner != &spl_token::id() && buyer.data_is_empty() && buyer.lamports() > 0) )] #[account(mut, signer, constraint= (treasury.owner == &spl_token::id() && buyer.owner == &spl_token::id()) || (treasury.owner != &spl_token::id() && buyer.data_is_empty() && buyer.lamports() > 0) )]
buyer: AccountInfo<'info>, buyer: AccountInfo<'info>,
#[account(mut, signer)] #[account(mut, signer)]
@ -70,11 +113,17 @@ pub struct PurchaseTicket<'info> {
rent: Sysvar<'info, Rent>, rent: Sysvar<'info, Rent>,
} }
/// IN phase 1, you can adjust up or down in any way
/// In phase 2, you can adjust up or down in any way
/// In phase 3, if you are above the decided_median, you can only adjust down to decided median. If below, you can only
/// adjust down, never up.
#[derive(Accounts)] #[derive(Accounts)]
#[instruction(amount: u64)] #[instruction(amount: u64)]
pub struct AdjustTicket<'info> { pub struct AdjustTicket<'info> {
#[account(mut, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), buyer.key.as_ref(), &[fair_launch_ticket.bump]], has_one=buyer, has_one=fair_launch)] #[account(mut, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), buyer.key.as_ref(), &[fair_launch_ticket.bump]], has_one=buyer, has_one=fair_launch)]
fair_launch_ticket: ProgramAccount<'info, FairLaunchTicket>, fair_launch_ticket: ProgramAccount<'info, FairLaunchTicket>,
#[account(seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), &[fair_launch.bump]])]
fair_launch: ProgramAccount<'info, FairLaunch>, fair_launch: ProgramAccount<'info, FairLaunch>,
#[account(mut)] #[account(mut)]
treasury: AccountInfo<'info>, treasury: AccountInfo<'info>,
@ -85,6 +134,26 @@ pub struct AdjustTicket<'info> {
#[account(address = system_program::ID)] #[account(address = system_program::ID)]
system_program: AccountInfo<'info>, system_program: AccountInfo<'info>,
} }
#[derive(Accounts)]
pub struct PunchTicket<'info> {
#[account(mut, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), buyer.key.as_ref(), &[fair_launch_ticket.bump]], has_one=buyer, has_one=fair_launch)]
fair_launch_ticket: ProgramAccount<'info, FairLaunchTicket>,
#[account(seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), &[fair_launch.bump]], has_one=token_mint)]
fair_launch: ProgramAccount<'info, FairLaunch>,
#[account(mut, signer)]
buyer: AccountInfo<'info>,
#[account(mut, owner=spl_token::id(), token::mint=token_mint, token::authority=buyer)]
buyer_token_account: CpiAccount<'info, TokenAccount>,
#[account(seeds=[PREFIX.as_bytes(), fair_launch.authority.as_ref(), MINT.as_bytes(), fair_launch.data.uuid.as_bytes()])]
token_mint: AccountInfo<'info>,
#[account(address = spl_token::id())]
token_program: AccountInfo<'info>,
}
pub const FAIR_LAUNCH_LOTTERY_SIZE: usize = 8 + // discriminator
32 + // fair launch
1 + // bump
4; // size of bitmask ones
pub const FAIR_LAUNCH_SPACE_VEC_START: usize = 8 + // discriminator pub const FAIR_LAUNCH_SPACE_VEC_START: usize = 8 + // discriminator
32 + // token_mint 32 + // token_mint
@ -99,10 +168,14 @@ pub const FAIR_LAUNCH_SPACE_VEC_START: usize = 8 + // discriminator
8 + // phase one start 8 + // phase one start
8 + // phase one end 8 + // phase one end
8 + // phase two end 8 + // phase two end
8 + // phase three end 9 + // phase three start
9 + // phase three end
8 + // tick size 8 + // tick size
8 + // number of tokens provided 8 + // number of tokens
8 + // number of tickets sold 8 + // number of tickets sold in phase 1
8 + // number of tickets remaining at the end in phase 2
8 + // number of tickets punched in phase 3
9 + // decided median,
4; // u32 representing number of amounts in vec so far 4; // u32 representing number of amounts in vec so far
pub const FAIR_LAUNCH_TICKET_SIZE: usize = 8 + // discriminator pub const FAIR_LAUNCH_TICKET_SIZE: usize = 8 + // discriminator
@ -110,7 +183,12 @@ pub const FAIR_LAUNCH_TICKET_SIZE: usize = 8 + // discriminator
32 + // buyer 32 + // buyer
8 + // amount paid in so far 8 + // amount paid in so far
1 + // state 1 + // state
1; // bump 1 + // bump
8; // seq
pub const FAIR_LAUNCH_TICKET_SEQ_SIZE: usize = 8 + //discriminator
32 + // fair launch ticket reverse lookup
8; //seq
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Default)] #[derive(AnchorSerialize, AnchorDeserialize, Clone, Default)]
pub struct FairLaunchData { pub struct FairLaunchData {
@ -120,9 +198,10 @@ pub struct FairLaunchData {
pub phase_one_start: UnixTimestamp, pub phase_one_start: UnixTimestamp,
pub phase_one_end: UnixTimestamp, pub phase_one_end: UnixTimestamp,
pub phase_two_end: UnixTimestamp, pub phase_two_end: UnixTimestamp,
pub phase_three_end: UnixTimestamp, pub phase_three_start: Option<UnixTimestamp>,
pub phase_three_end: Option<UnixTimestamp>,
pub tick_size: u64, pub tick_size: u64,
pub number_of_tokens_provided: u64, pub number_of_tokens: u64,
} }
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Default)] #[derive(AnchorSerialize, AnchorDeserialize, Clone, Default)]
@ -137,10 +216,21 @@ pub struct FairLaunch {
pub treasury_bump: u8, pub treasury_bump: u8,
pub token_mint_bump: u8, pub token_mint_bump: u8,
pub data: FairLaunchData, pub data: FairLaunchData,
pub number_tickets_sold: u64, pub number_tickets_sold_in_phase_1: u64,
pub number_tickets_remaining_in_phase_2: u64,
pub number_tickets_punched_in_phase_3: u64,
pub decided_median: Option<u64>,
pub median: Vec<MedianTuple>, pub median: Vec<MedianTuple>,
} }
#[account]
pub struct FairLaunchLotteryBitmap {
pub fair_launch: Pubkey,
pub bump: u8,
/// This must be exactly the number of winners and is incremented precisely in each strip addition
pub bitmap_ones: u32
}
#[derive(AnchorSerialize, AnchorDeserialize, Clone)] #[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub enum FairLaunchTicketState { pub enum FairLaunchTicketState {
Unpunched, Unpunched,
@ -155,8 +245,17 @@ pub struct FairLaunchTicket {
pub amount: u64, pub amount: u64,
pub state: FairLaunchTicketState, pub state: FairLaunchTicketState,
pub bump: u8, pub bump: u8,
pub seq: u64,
} }
#[account]
pub struct FairLaunchTicketSeqLookup {
pub fair_launch_ticket: Pubkey,
pub seq: u64,
}
#[error] #[error]
pub enum ErrorCode { pub enum ErrorCode {
#[msg("Account does not have correct owner!")] #[msg("Account does not have correct owner!")]