use crate::{
deprecated_state::{AuctionManagerV1, ParticipationConfigV1},
error::MetaplexError,
state::{NonWinningConstraint, Store, WinningConstraint, PREFIX},
utils::{
assert_derivation, assert_initialized, assert_owned_by,
assert_store_safety_vault_manager_match, transfer_safety_deposit_box_items,
},
};
use mpl_auction::processor::{AuctionData, AuctionDataExtended, AuctionState};
use mpl_token_metadata::{
deprecated_instruction::deprecated_mint_printing_tokens_via_token,
state::{MasterEditionV1, TokenMetadataAccount},
};
use mpl_token_vault::state::SafetyDepositBox;
use solana_program::{
account_info::{next_account_info, AccountInfo},
entrypoint::ProgramResult,
program::invoke_signed,
pubkey::Pubkey,
};
use spl_token::{instruction::close_account, state::Account};
fn mint_printing_tokens<'a: 'b, 'b>(
program: &AccountInfo<'a>,
destination: &AccountInfo<'a>,
token: &AccountInfo<'a>,
one_time_printing_authorization_mint: &AccountInfo<'a>,
printing_mint: &AccountInfo<'a>,
burn_authority: &AccountInfo<'a>,
metadata: &AccountInfo<'a>,
master_edition: &AccountInfo<'a>,
token_program_info: &AccountInfo<'a>,
rent_info: &AccountInfo<'a>,
supply: u64,
authority_signer_seeds: &'b [&'b [u8]],
) -> ProgramResult {
let result = invoke_signed(
&deprecated_mint_printing_tokens_via_token(
*program.key,
*destination.key,
*token.key,
*one_time_printing_authorization_mint.key,
*printing_mint.key,
*burn_authority.key,
*metadata.key,
*master_edition.key,
supply,
),
&[
program.clone(),
destination.clone(),
token.clone(),
one_time_printing_authorization_mint.clone(),
printing_mint.clone(),
burn_authority.clone(),
master_edition.clone(),
metadata.clone(),
token_program_info.clone(),
rent_info.clone(),
],
&[authority_signer_seeds],
);
result.map_err(|_| MetaplexError::PrintingAuthorizationTokensFailed.into())
}
#[allow(clippy::unnecessary_cast)]
#[allow(clippy::absurd_extreme_comparisons)]
pub fn process_deprecated_populate_participation_printing_account<'a>(
program_id: &'a Pubkey,
accounts: &'a [AccountInfo<'a>],
) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let safety_deposit_token_store_info = next_account_info(account_info_iter)?;
let transient_one_time_holding_info = next_account_info(account_info_iter)?;
let participation_printing_holding_account_info = next_account_info(account_info_iter)?;
let one_time_printing_authorization_mint_info = next_account_info(account_info_iter)?;
let printing_mint_info = next_account_info(account_info_iter)?;
let safety_deposit_info = next_account_info(account_info_iter)?;
let vault_info = next_account_info(account_info_iter)?;
let fraction_mint_info = next_account_info(account_info_iter)?;
let auction_info = next_account_info(account_info_iter)?;
let auction_extended_info = next_account_info(account_info_iter)?;
let auction_manager_info = next_account_info(account_info_iter)?;
let token_program_info = next_account_info(account_info_iter)?;
let token_vault_program_info = next_account_info(account_info_iter)?;
let token_metadata_program_info = next_account_info(account_info_iter)?;
let store_info = next_account_info(account_info_iter)?;
let master_edition_info = next_account_info(account_info_iter)?;
let metadata_info = next_account_info(account_info_iter)?;
let transfer_authority_info = next_account_info(account_info_iter)?;
let payer_info = next_account_info(account_info_iter)?;
let rent_info = next_account_info(account_info_iter)?;
let auction_manager = AuctionManagerV1::from_account_info(auction_manager_info)?;
let safety_deposit = SafetyDepositBox::from_account_info(safety_deposit_info)?;
let safety_deposit_token_store: Account = assert_initialized(&safety_deposit_token_store_info)?;
let auction = AuctionData::from_account_info(auction_info)?;
let auction_extended = AuctionDataExtended::from_account_info(auction_extended_info)?;
let master_edition = MasterEditionV1::from_account_info(master_edition_info)?;
let transient_one_time_auth_holding_account: Account =
assert_initialized(transient_one_time_holding_info)?;
let participation_printing_account: Account =
assert_initialized(participation_printing_holding_account_info)?;
let store = Store::from_account_info(store_info)?;
let config: &ParticipationConfigV1;
if let Some(part_config) = &auction_manager.settings.participation_config {
config = part_config
} else {
return Err(MetaplexError::NotEligibleForParticipation.into());
}
if auction_manager.auction != *auction_info.key {
return Err(MetaplexError::AuctionManagerAuctionMismatch.into());
}
if auction.state != AuctionState::Ended {
return Err(MetaplexError::AuctionHasNotEnded.into());
}
assert_store_safety_vault_manager_match(
&auction_manager.authority,
&safety_deposit_info,
&vault_info,
&store.token_vault_program,
)?;
assert_owned_by(transient_one_time_holding_info, token_program_info.key)?;
assert_owned_by(safety_deposit_token_store_info, token_program_info.key)?;
assert_owned_by(
participation_printing_holding_account_info,
token_program_info.key,
)?;
assert_owned_by(
one_time_printing_authorization_mint_info,
token_program_info.key,
)?;
assert_owned_by(printing_mint_info, token_program_info.key)?;
assert_owned_by(safety_deposit_info, &store.token_vault_program)?;
assert_owned_by(vault_info, &store.token_vault_program)?;
assert_owned_by(fraction_mint_info, token_program_info.key)?;
assert_owned_by(auction_info, &store.auction_program)?;
assert_owned_by(auction_extended_info, &store.auction_program)?;
assert_owned_by(auction_manager_info, program_id)?;
assert_owned_by(store_info, program_id)?;
assert_owned_by(master_edition_info, &store.token_metadata_program)?;
assert_owned_by(metadata_info, &store.token_metadata_program)?;
if transient_one_time_auth_holding_account.owner != *auction_manager_info.key {
return Err(MetaplexError::IncorrectOwner.into());
}
if transient_one_time_auth_holding_account.mint
!= master_edition.one_time_printing_authorization_mint
{
return Err(MetaplexError::TransientAuthAccountMintMismatch.into());
}
if store.token_program != *token_program_info.key {
return Err(MetaplexError::TokenProgramMismatch.into());
}
if store.token_vault_program != *token_vault_program_info.key {
return Err(MetaplexError::TokenProgramMismatch.into());
}
if store.token_metadata_program != *token_metadata_program_info.key {
return Err(MetaplexError::TokenProgramMismatch.into());
}
if master_edition.one_time_printing_authorization_mint != safety_deposit.token_mint {
return Err(MetaplexError::SafetyDepositBoxMasterEditionOneTimeAuthMintMismatch.into());
}
if master_edition.one_time_printing_authorization_mint
!= *one_time_printing_authorization_mint_info.key
{
return Err(MetaplexError::MasterEditionOneTimeAuthMintMismatch.into());
}
if master_edition.printing_mint != *printing_mint_info.key {
return Err(MetaplexError::MasterEditionMintMismatch.into());
}
if let Some(state) = &auction_manager.state.participation_state {
if let Some(token) = state.printing_authorization_token_account {
if *participation_printing_holding_account_info.key != token {
return Err(MetaplexError::PrintingAuthorizationTokenAccountMismatch.into());
}
}
}
assert_derivation(
&store.auction_program,
auction_extended_info,
&[
mpl_auction::PREFIX.as_bytes(),
store.auction_program.as_ref(),
vault_info.key.as_ref(),
mpl_auction::EXTENDED.as_bytes(),
],
)?;
if participation_printing_account.amount == 0 && safety_deposit_token_store.amount > 0 {
let auction_bump_seed = assert_derivation(
program_id,
auction_manager_info,
&[PREFIX.as_bytes(), &auction_manager.auction.as_ref()],
)?;
let auction_auth_seeds = &[
PREFIX.as_bytes(),
&auction_manager.auction.as_ref(),
&[auction_bump_seed],
];
transfer_safety_deposit_box_items(
token_vault_program_info.clone(),
transient_one_time_holding_info.clone(),
safety_deposit_info.clone(),
safety_deposit_token_store_info.clone(),
vault_info.clone(),
fraction_mint_info.clone(),
auction_manager_info.clone(),
transfer_authority_info.clone(),
rent_info.clone(),
1,
auction_auth_seeds,
)?;
let mut amount_to_mint = auction_extended.total_uncancelled_bids;
if config.winner_constraint == WinningConstraint::NoParticipationPrize {
amount_to_mint = amount_to_mint
.checked_sub(auction.num_winners())
.ok_or(MetaplexError::NumericalOverflowError)?;
} else if config.non_winning_constraint == NonWinningConstraint::NoParticipationPrize {
amount_to_mint = auction.num_winners();
}
mint_printing_tokens(
token_metadata_program_info,
participation_printing_holding_account_info,
transient_one_time_holding_info,
one_time_printing_authorization_mint_info,
printing_mint_info,
auction_manager_info,
metadata_info,
master_edition_info,
token_program_info,
rent_info,
amount_to_mint,
auction_auth_seeds,
)?;
invoke_signed(
&close_account(
token_program_info.key,
transient_one_time_holding_info.key,
payer_info.key,
auction_manager_info.key,
&[auction_manager_info.key],
)?,
&[
token_program_info.clone(),
transient_one_time_holding_info.clone(),
payer_info.clone(),
auction_manager_info.clone(),
],
&[auction_auth_seeds],
)?;
}
Ok(())
}