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
2 changes: 2 additions & 0 deletions programs/v06_launchpad/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,6 @@ pub enum LaunchpadError {
LaunchNotLive,
#[msg("Minimum raise amount must be greater than or equal to $0.5 so that there's enough liquidity for the launch")]
InvalidMinimumRaiseAmount,
#[msg("Invalid admin")]
InvalidAdmin,
}
8 changes: 8 additions & 0 deletions programs/v06_launchpad/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,11 @@ pub struct LaunchCloseEvent {
pub launch: Pubkey,
pub new_state: LaunchState,
}

#[event]
pub struct LaunchFundsReturnedEvent {
pub common: CommonFields,
pub launch: Pubkey,
pub recipient: Pubkey,
pub usdc_returned: u64,
}
2 changes: 2 additions & 0 deletions programs/v06_launchpad/src/instructions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod complete_launch;
pub mod fund;
pub mod initialize_launch;
pub mod refund;
pub mod return_funds;
pub mod start_launch;

pub use claim::*;
Expand All @@ -12,4 +13,5 @@ pub use complete_launch::*;
pub use fund::*;
pub use initialize_launch::*;
pub use refund::*;
pub use return_funds::*;
pub use start_launch::*;
96 changes: 96 additions & 0 deletions programs/v06_launchpad/src/instructions/return_funds.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use anchor_lang::prelude::*;
use anchor_spl::token::{self, Token, TokenAccount, Transfer};

use crate::events::{CommonFields, LaunchFundsReturnedEvent};
use crate::state::Launch;

pub mod admin {
use anchor_lang::prelude::declare_id;

// MetaDAO multisig vault
declare_id!("6awyHMshBGVjJ3ozdSJdyyDE1CTAXUwrpNMaRGMsb4sf");
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub struct ReturnFundsArgs {
pub amount: u64,
}

#[event_cpi]
#[derive(Accounts)]
pub struct ReturnFunds<'info> {
pub admin: Signer<'info>,

#[account(
mut,
has_one = launch_quote_vault,
has_one = launch_signer,
)]
pub launch: Account<'info, Launch>,

#[account(mut)]
pub launch_quote_vault: Account<'info, TokenAccount>,

/// CHECK: This is the launch signer
#[account(
seeds = [b"launch_signer", launch.key().as_ref()],
bump
)]
pub launch_signer: UncheckedAccount<'info>,

/// CHECK: not used, just for constraints
pub recipient: UncheckedAccount<'info>,

#[account(mut, associated_token::mint = launch.quote_mint, associated_token::authority = recipient)]
pub recipient_quote_account: Account<'info, TokenAccount>,

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

impl ReturnFunds<'_> {
pub fn validate(&self) -> Result<()> {
#[cfg(feature = "production")]
require_keys_eq!(self.admin.key(), admin::ID, LaunchpadError::InvalidAdmin);

Ok(())
}

pub fn handle(ctx: Context<Self>, args: ReturnFundsArgs) -> Result<()> {
let launch = &mut ctx.accounts.launch;
let launch_key = launch.key();

let seeds = &[
b"launch_signer",
launch_key.as_ref(),
&[launch.launch_signer_pda_bump],
];
let signer = &[&seeds[..]];

// Transfer USDC back to the recipient
token::transfer(
CpiContext::new_with_signer(
ctx.accounts.token_program.to_account_info(),
Transfer {
from: ctx.accounts.launch_quote_vault.to_account_info(),
to: ctx.accounts.recipient_quote_account.to_account_info(),
authority: ctx.accounts.launch_signer.to_account_info(),
},
signer,
),
args.amount,
)?;

launch.seq_num += 1;

let clock = Clock::get()?;
emit_cpi!(LaunchFundsReturnedEvent {
common: CommonFields::new(&clock, launch.seq_num),
launch: ctx.accounts.launch.key(),
recipient: ctx.accounts.recipient.key(),
usdc_returned: args.amount,
});

Ok(())
}
}
5 changes: 5 additions & 0 deletions programs/v06_launchpad/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,9 @@ pub mod launchpad {
pub fn close_launch(ctx: Context<CloseLaunch>) -> Result<()> {
CloseLaunch::handle(ctx)
}

#[access_control(ctx.accounts.validate())]
pub fn return_funds(ctx: Context<ReturnFunds>, args: ReturnFundsArgs) -> Result<()> {
ReturnFunds::handle(ctx, args)
}
}
Loading
Loading