diff --git a/programs/libreplex_editions/src/instructions/claim_update_authority.rs b/programs/libreplex_editions/src/instructions/claim_update_authority.rs index 5181e360..a350b391 100644 --- a/programs/libreplex_editions/src/instructions/claim_update_authority.rs +++ b/programs/libreplex_editions/src/instructions/claim_update_authority.rs @@ -16,6 +16,9 @@ pub struct ClaimUpdateAuthorityCtx<'info> { #[account(mut)] pub payer: Signer<'info>, + #[account(mut)] + pub creator: Signer<'info>, + #[account(mut)] pub mint: AccountInfo<'info>, @@ -35,11 +38,10 @@ pub fn claim_update_authority<'info>(ctx: Context<'_, '_, '_, 'info, ClaimUpdate let mint = &ctx.accounts.mint; let token_program = &ctx.accounts.token_program; let editions_deployment = &ctx.accounts.editions_deployment; - let payer = &ctx.accounts.payer; + let creator = &ctx.accounts.creator; require!(editions_deployment.max_number_of_tokens == editions_deployment.number_of_tokens_issued, EditionsError::MintNotComplete); - require!(editions_deployment.creator.key() == payer.key(), EditionsError::InvalidCreator); - require!(payer.is_signer, EditionsError::InvalidSigner); + require!(editions_deployment.creator.key() == creator.key(), EditionsError::InvalidCreator); let deployment_seeds: &[&[u8]] = &[ "editions_deployment".as_bytes(), @@ -48,19 +50,19 @@ pub fn claim_update_authority<'info>(ctx: Context<'_, '_, '_, 'info, ClaimUpdate ]; let account_infos = [ - payer.to_account_info(), editions_deployment.to_account_info(), - mint.to_account_info(), + mint.to_account_info(), + creator.to_account_info(), token_program.to_account_info(), ]; - let payer = OptionalNonZeroPubkey::try_from(Some(payer.to_account_info().key()))?; + let creator_key: OptionalNonZeroPubkey = OptionalNonZeroPubkey::try_from(Some(creator.to_account_info().key()))?; let update_authority_ix = update_authority( &spl_token_2022::ID, &mint.key(), &editions_deployment.key(), - payer + creator_key ); invoke_signed(&update_authority_ix, &account_infos, &[deployment_seeds])?; diff --git a/programs/libreplex_editions_controls/src/errors.rs b/programs/libreplex_editions_controls/src/errors.rs index 53e98476..c3351d54 100644 --- a/programs/libreplex_editions_controls/src/errors.rs +++ b/programs/libreplex_editions_controls/src/errors.rs @@ -31,5 +31,11 @@ pub enum EditionsError { InvalidMetadata, #[msg("Creator fee too high")] - CreatorFeeTooHigh -} + CreatorFeeTooHigh, + + #[msg("Invalid creator")] + InvalidCreator, + + #[msg("Invalid signer")] + InvalidSigner, +} \ No newline at end of file diff --git a/programs/libreplex_editions_controls/src/instructions/claim_update_authority.rs b/programs/libreplex_editions_controls/src/instructions/claim_update_authority.rs new file mode 100644 index 00000000..fcc337a9 --- /dev/null +++ b/programs/libreplex_editions_controls/src/instructions/claim_update_authority.rs @@ -0,0 +1,96 @@ +use anchor_lang::{prelude::*, solana_program::program::invoke_signed}; +use anchor_spl::token_2022; +use libreplex_editions::cpi::accounts::ClaimUpdateAuthorityCtx as CpiClaimUpdateAuthorityCtx; +use libreplex_editions::program::LibreplexEditions; +use crate::EditionsControls; +use crate::errors::EditionsError; +use spl_token_metadata_interface::instruction::update_authority; +use spl_pod::optional_keys::OptionalNonZeroPubkey; +#[derive(Accounts)] +pub struct ClaimUpdateAuthorityCtx<'info> { + + #[account(mut, + seeds = [ + b"editions_controls", editions_deployment.key().as_ref() + ], bump)] + pub editions_controls: Account<'info, EditionsControls>, + + #[account(mut)] + pub editions_deployment: UncheckedAccount<'info>, + + #[account(mut)] + pub payer: Signer<'info>, + + #[account(mut)] + pub creator: Signer<'info>, + + #[account(mut)] + pub mint: AccountInfo<'info>, + + /* BOILERPLATE PROGRAM ACCOUNTS */ + /// CHECK: Checked in constraint + #[account( + constraint = token_program.key() == token_2022::ID + )] + pub token_program: UncheckedAccount<'info>, + + #[account()] + pub system_program: Program<'info, System>, + + pub libreplex_editions_program: Program<'info, LibreplexEditions> + +} + +pub fn claim_update_authority<'info>(ctx: Context<'_, '_, '_, 'info, ClaimUpdateAuthorityCtx<'info>>) -> Result<()> { + let mint = &ctx.accounts.mint; + let token_program = &ctx.accounts.token_program; + let editions_controls = &ctx.accounts.editions_controls; + let editions_deployment = &ctx.accounts.editions_deployment; + let system_program = &ctx.accounts.system_program; + let payer = &ctx.accounts.payer; + let libreplex_editions_program = &ctx.accounts.libreplex_editions_program; + let creator = &ctx.accounts.creator; + + require!(editions_controls.creator.key() == creator.key(), EditionsError::InvalidCreator); + let editions_deployment_key = editions_deployment.key(); + + let seeds = &[ + b"editions_controls", + editions_deployment_key.as_ref(), + &[ctx.bumps.editions_controls], + ]; + + libreplex_editions::cpi::claim_update_authority( + CpiContext::new_with_signer( + libreplex_editions_program.to_account_info(), + CpiClaimUpdateAuthorityCtx { + editions_deployment: editions_deployment.to_account_info(), + mint: mint.to_account_info(), + payer: payer.to_account_info(), + creator: editions_controls.to_account_info(), + token_program: token_program.to_account_info(), + system_program: system_program.to_account_info(), + }, + &[seeds] + ))?; + + let account_infos = [ + editions_controls.to_account_info(), + mint.to_account_info(), + creator.to_account_info(), + token_program.to_account_info(), + ]; + + let creator_key: OptionalNonZeroPubkey = OptionalNonZeroPubkey::try_from(Some(creator.to_account_info().key()))?; + + let update_authority_ix = update_authority( + &spl_token_2022::ID, + &mint.key(), + &editions_controls.key(), + creator_key + ); + + invoke_signed(&update_authority_ix, &account_infos, &[seeds])?; + + Ok(()) +} \ No newline at end of file diff --git a/programs/libreplex_editions_controls/src/instructions/mod.rs b/programs/libreplex_editions_controls/src/instructions/mod.rs index be25f38b..636cb25c 100644 --- a/programs/libreplex_editions_controls/src/instructions/mod.rs +++ b/programs/libreplex_editions_controls/src/instructions/mod.rs @@ -13,3 +13,7 @@ pub use add_phase::*; pub mod mint_with_controls; pub use mint_with_controls::*; +pub mod claim_update_authority; +pub use claim_update_authority::*; + + diff --git a/target/types/libreplex_editions.ts b/target/types/libreplex_editions.ts index f0e4e212..6847d0ba 100644 --- a/target/types/libreplex_editions.ts +++ b/target/types/libreplex_editions.ts @@ -149,6 +149,11 @@ export type LibreplexEditions = { "isMut": true, "isSigner": true }, + { + "name": "creator", + "isMut": true, + "isSigner": true + }, { "name": "mint", "isMut": true, @@ -545,6 +550,11 @@ export const IDL: LibreplexEditions = { "isMut": true, "isSigner": true }, + { + "name": "creator", + "isMut": true, + "isSigner": true + }, { "name": "mint", "isMut": true, diff --git a/target/types/libreplex_editions_controls.ts b/target/types/libreplex_editions_controls.ts index 3da404ea..ae614fc6 100644 --- a/target/types/libreplex_editions_controls.ts +++ b/target/types/libreplex_editions_controls.ts @@ -538,6 +538,16 @@ export type LibreplexEditionsControls = { "code": 6009, "name": "CreatorFeeTooHigh", "msg": "Creator fee too high" + }, + { + "code": 6010, + "name": "InvalidCreator", + "msg": "Invalid creator" + }, + { + "code": 6011, + "name": "InvalidSigner", + "msg": "Invalid signer" } ] }; @@ -1082,6 +1092,16 @@ export const IDL: LibreplexEditionsControls = { "code": 6009, "name": "CreatorFeeTooHigh", "msg": "Creator fee too high" + }, + { + "code": 6010, + "name": "InvalidCreator", + "msg": "Invalid creator" + }, + { + "code": 6011, + "name": "InvalidSigner", + "msg": "Invalid signer" } ] };