From a9edef2e7f211fc73b69e095dd36623ce7e472f5 Mon Sep 17 00:00:00 2001 From: blockiosaurus Date: Wed, 28 Feb 2024 21:38:48 -0500 Subject: [PATCH] Fixing update for create. --- .../js/src/generated/errors/mplCoreProgram.ts | 13 ++ .../js/src/generated/instructions/create.ts | 17 +-- .../src/generated/errors/mpl_core_program.rs | 3 + .../rust/src/generated/instructions/create.rs | 118 +++++++++++++----- idls/mpl_core_program.json | 18 ++- programs/mpl-core/src/error.rs | 4 + programs/mpl-core/src/instruction.rs | 7 +- programs/mpl-core/src/processor/create.rs | 2 - .../mpl-core/src/state/update_authority.rs | 14 ++- 9 files changed, 146 insertions(+), 50 deletions(-) diff --git a/clients/js/src/generated/errors/mplCoreProgram.ts b/clients/js/src/generated/errors/mplCoreProgram.ts index 57963158..d66660f1 100644 --- a/clients/js/src/generated/errors/mplCoreProgram.ts +++ b/clients/js/src/generated/errors/mplCoreProgram.ts @@ -278,6 +278,19 @@ export class InvalidCollectionError extends ProgramError { codeToErrorMap.set(0x13, InvalidCollectionError); nameToErrorMap.set('InvalidCollection', InvalidCollectionError); +/** MissingUpdateAuthority: Missing update authority */ +export class MissingUpdateAuthorityError extends ProgramError { + readonly name: string = 'MissingUpdateAuthority'; + + readonly code: number = 0x14; // 20 + + constructor(program: Program, cause?: Error) { + super('Missing update authority', program, cause); + } +} +codeToErrorMap.set(0x14, MissingUpdateAuthorityError); +nameToErrorMap.set('MissingUpdateAuthority', MissingUpdateAuthorityError); + /** * Attempts to resolve a custom program error from the provided error code. * @category Errors diff --git a/clients/js/src/generated/instructions/create.ts b/clients/js/src/generated/instructions/create.ts index a2bb664c..b0d68d9c 100644 --- a/clients/js/src/generated/instructions/create.ts +++ b/clients/js/src/generated/instructions/create.ts @@ -42,12 +42,14 @@ export type CreateInstructionAccounts = { assetAddress: Signer; /** The collection to which the asset belongs */ collection?: PublicKey | Pda; - /** The authority of the new asset */ - updateAuthority?: PublicKey | Pda; + /** The authority signing for creation */ + authority?: PublicKey | Pda; /** The account paying for the storage fees */ payer?: Signer; /** The owner of the new asset. Defaults to the authority if not present. */ owner?: PublicKey | Pda; + /** The authority on the new asset */ + updateAuthority?: PublicKey | Pda; /** The system program */ systemProgram?: PublicKey | Pda; /** The SPL Noop Program */ @@ -111,20 +113,21 @@ export function create( value: input.assetAddress ?? null, }, collection: { index: 1, isWritable: true, value: input.collection ?? null }, + authority: { index: 2, isWritable: false, value: input.authority ?? null }, + payer: { index: 3, isWritable: true, value: input.payer ?? null }, + owner: { index: 4, isWritable: false, value: input.owner ?? null }, updateAuthority: { - index: 2, + index: 5, isWritable: false, value: input.updateAuthority ?? null, }, - payer: { index: 3, isWritable: true, value: input.payer ?? null }, - owner: { index: 4, isWritable: false, value: input.owner ?? null }, systemProgram: { - index: 5, + index: 6, isWritable: false, value: input.systemProgram ?? null, }, logWrapper: { - index: 6, + index: 7, isWritable: false, value: input.logWrapper ?? null, }, diff --git a/clients/rust/src/generated/errors/mpl_core_program.rs b/clients/rust/src/generated/errors/mpl_core_program.rs index b4fe9f7d..2082600f 100644 --- a/clients/rust/src/generated/errors/mpl_core_program.rs +++ b/clients/rust/src/generated/errors/mpl_core_program.rs @@ -70,6 +70,9 @@ pub enum MplCoreProgramError { /// 19 (0x13) - Invalid Collection passed in #[error("Invalid Collection passed in")] InvalidCollection, + /// 20 (0x14) - Missing update authority + #[error("Missing update authority")] + MissingUpdateAuthority, } impl solana_program::program_error::PrintProgramError for MplCoreProgramError { diff --git a/clients/rust/src/generated/instructions/create.rs b/clients/rust/src/generated/instructions/create.rs index 0b9d5bde..fa847fa4 100644 --- a/clients/rust/src/generated/instructions/create.rs +++ b/clients/rust/src/generated/instructions/create.rs @@ -16,12 +16,14 @@ pub struct Create { pub asset_address: solana_program::pubkey::Pubkey, /// The collection to which the asset belongs pub collection: Option, - /// The authority of the new asset - pub update_authority: Option, + /// The authority signing for creation + pub authority: Option, /// The account paying for the storage fees pub payer: solana_program::pubkey::Pubkey, /// The owner of the new asset. Defaults to the authority if not present. pub owner: Option, + /// The authority on the new asset + pub update_authority: Option, /// The system program pub system_program: solana_program::pubkey::Pubkey, /// The SPL Noop Program @@ -41,7 +43,7 @@ impl Create { args: CreateInstructionArgs, remaining_accounts: &[solana_program::instruction::AccountMeta], ) -> solana_program::instruction::Instruction { - let mut accounts = Vec::with_capacity(7 + remaining_accounts.len()); + let mut accounts = Vec::with_capacity(8 + remaining_accounts.len()); accounts.push(solana_program::instruction::AccountMeta::new( self.asset_address, true, @@ -56,10 +58,9 @@ impl Create { false, )); } - if let Some(update_authority) = self.update_authority { + if let Some(authority) = self.authority { accounts.push(solana_program::instruction::AccountMeta::new_readonly( - update_authority, - false, + authority, false, )); } else { accounts.push(solana_program::instruction::AccountMeta::new_readonly( @@ -80,6 +81,17 @@ impl Create { false, )); } + if let Some(update_authority) = self.update_authority { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + update_authority, + false, + )); + } else { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + crate::MPL_CORE_PROGRAM_ID, + false, + )); + } accounts.push(solana_program::instruction::AccountMeta::new_readonly( self.system_program, false, @@ -133,9 +145,10 @@ pub struct CreateInstructionArgs { pub struct CreateBuilder { asset_address: Option, collection: Option, - update_authority: Option, + authority: Option, payer: Option, owner: Option, + update_authority: Option, system_program: Option, log_wrapper: Option, data_state: Option, @@ -163,13 +176,10 @@ impl CreateBuilder { self } /// `[optional account]` - /// The authority of the new asset + /// The authority signing for creation #[inline(always)] - pub fn update_authority( - &mut self, - update_authority: Option, - ) -> &mut Self { - self.update_authority = update_authority; + pub fn authority(&mut self, authority: Option) -> &mut Self { + self.authority = authority; self } /// The account paying for the storage fees @@ -185,6 +195,16 @@ impl CreateBuilder { self.owner = owner; self } + /// `[optional account]` + /// The authority on the new asset + #[inline(always)] + pub fn update_authority( + &mut self, + update_authority: Option, + ) -> &mut Self { + self.update_authority = update_authority; + self + } /// `[optional account, default to '11111111111111111111111111111111']` /// The system program #[inline(always)] @@ -245,9 +265,10 @@ impl CreateBuilder { let accounts = Create { asset_address: self.asset_address.expect("asset_address is not set"), collection: self.collection, - update_authority: self.update_authority, + authority: self.authority, payer: self.payer.expect("payer is not set"), owner: self.owner, + update_authority: self.update_authority, system_program: self .system_program .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), @@ -270,12 +291,14 @@ pub struct CreateCpiAccounts<'a, 'b> { pub asset_address: &'b solana_program::account_info::AccountInfo<'a>, /// The collection to which the asset belongs pub collection: Option<&'b solana_program::account_info::AccountInfo<'a>>, - /// The authority of the new asset - pub update_authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + /// The authority signing for creation + pub authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, /// The account paying for the storage fees pub payer: &'b solana_program::account_info::AccountInfo<'a>, /// The owner of the new asset. Defaults to the authority if not present. pub owner: Option<&'b solana_program::account_info::AccountInfo<'a>>, + /// The authority on the new asset + pub update_authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, /// The system program pub system_program: &'b solana_program::account_info::AccountInfo<'a>, /// The SPL Noop Program @@ -290,12 +313,14 @@ pub struct CreateCpi<'a, 'b> { pub asset_address: &'b solana_program::account_info::AccountInfo<'a>, /// The collection to which the asset belongs pub collection: Option<&'b solana_program::account_info::AccountInfo<'a>>, - /// The authority of the new asset - pub update_authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + /// The authority signing for creation + pub authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, /// The account paying for the storage fees pub payer: &'b solana_program::account_info::AccountInfo<'a>, /// The owner of the new asset. Defaults to the authority if not present. pub owner: Option<&'b solana_program::account_info::AccountInfo<'a>>, + /// The authority on the new asset + pub update_authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, /// The system program pub system_program: &'b solana_program::account_info::AccountInfo<'a>, /// The SPL Noop Program @@ -314,9 +339,10 @@ impl<'a, 'b> CreateCpi<'a, 'b> { __program: program, asset_address: accounts.asset_address, collection: accounts.collection, - update_authority: accounts.update_authority, + authority: accounts.authority, payer: accounts.payer, owner: accounts.owner, + update_authority: accounts.update_authority, system_program: accounts.system_program, log_wrapper: accounts.log_wrapper, __args: args, @@ -355,7 +381,7 @@ impl<'a, 'b> CreateCpi<'a, 'b> { bool, )], ) -> solana_program::entrypoint::ProgramResult { - let mut accounts = Vec::with_capacity(7 + remaining_accounts.len()); + let mut accounts = Vec::with_capacity(8 + remaining_accounts.len()); accounts.push(solana_program::instruction::AccountMeta::new( *self.asset_address.key, true, @@ -371,9 +397,9 @@ impl<'a, 'b> CreateCpi<'a, 'b> { false, )); } - if let Some(update_authority) = self.update_authority { + if let Some(authority) = self.authority { accounts.push(solana_program::instruction::AccountMeta::new_readonly( - *update_authority.key, + *authority.key, false, )); } else { @@ -396,6 +422,17 @@ impl<'a, 'b> CreateCpi<'a, 'b> { false, )); } + if let Some(update_authority) = self.update_authority { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *update_authority.key, + false, + )); + } else { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + crate::MPL_CORE_PROGRAM_ID, + false, + )); + } accounts.push(solana_program::instruction::AccountMeta::new_readonly( *self.system_program.key, false, @@ -427,19 +464,22 @@ impl<'a, 'b> CreateCpi<'a, 'b> { accounts, data, }; - let mut account_infos = Vec::with_capacity(7 + 1 + remaining_accounts.len()); + let mut account_infos = Vec::with_capacity(8 + 1 + remaining_accounts.len()); account_infos.push(self.__program.clone()); account_infos.push(self.asset_address.clone()); if let Some(collection) = self.collection { account_infos.push(collection.clone()); } - if let Some(update_authority) = self.update_authority { - account_infos.push(update_authority.clone()); + if let Some(authority) = self.authority { + account_infos.push(authority.clone()); } account_infos.push(self.payer.clone()); if let Some(owner) = self.owner { account_infos.push(owner.clone()); } + if let Some(update_authority) = self.update_authority { + account_infos.push(update_authority.clone()); + } account_infos.push(self.system_program.clone()); if let Some(log_wrapper) = self.log_wrapper { account_infos.push(log_wrapper.clone()); @@ -467,9 +507,10 @@ impl<'a, 'b> CreateCpiBuilder<'a, 'b> { __program: program, asset_address: None, collection: None, - update_authority: None, + authority: None, payer: None, owner: None, + update_authority: None, system_program: None, log_wrapper: None, data_state: None, @@ -500,13 +541,13 @@ impl<'a, 'b> CreateCpiBuilder<'a, 'b> { self } /// `[optional account]` - /// The authority of the new asset + /// The authority signing for creation #[inline(always)] - pub fn update_authority( + pub fn authority( &mut self, - update_authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, ) -> &mut Self { - self.instruction.update_authority = update_authority; + self.instruction.authority = authority; self } /// The account paying for the storage fees @@ -525,6 +566,16 @@ impl<'a, 'b> CreateCpiBuilder<'a, 'b> { self.instruction.owner = owner; self } + /// `[optional account]` + /// The authority on the new asset + #[inline(always)] + pub fn update_authority( + &mut self, + update_authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.update_authority = update_authority; + self + } /// The system program #[inline(always)] pub fn system_program( @@ -629,12 +680,14 @@ impl<'a, 'b> CreateCpiBuilder<'a, 'b> { collection: self.instruction.collection, - update_authority: self.instruction.update_authority, + authority: self.instruction.authority, payer: self.instruction.payer.expect("payer is not set"), owner: self.instruction.owner, + update_authority: self.instruction.update_authority, + system_program: self .instruction .system_program @@ -654,9 +707,10 @@ struct CreateCpiBuilderInstruction<'a, 'b> { __program: &'b solana_program::account_info::AccountInfo<'a>, asset_address: Option<&'b solana_program::account_info::AccountInfo<'a>>, collection: Option<&'b solana_program::account_info::AccountInfo<'a>>, - update_authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, owner: Option<&'b solana_program::account_info::AccountInfo<'a>>, + update_authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, log_wrapper: Option<&'b solana_program::account_info::AccountInfo<'a>>, data_state: Option, diff --git a/idls/mpl_core_program.json b/idls/mpl_core_program.json index d58070fc..a0e70a11 100644 --- a/idls/mpl_core_program.json +++ b/idls/mpl_core_program.json @@ -23,12 +23,12 @@ ] }, { - "name": "updateAuthority", + "name": "authority", "isMut": false, "isSigner": false, "isOptional": true, "docs": [ - "The authority of the new asset" + "The authority signing for creation" ] }, { @@ -48,6 +48,15 @@ "The owner of the new asset. Defaults to the authority if not present." ] }, + { + "name": "updateAuthority", + "isMut": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "The authority on the new asset" + ] + }, { "name": "systemProgram", "isMut": false, @@ -1687,6 +1696,11 @@ "code": 19, "name": "InvalidCollection", "msg": "Invalid Collection passed in" + }, + { + "code": 20, + "name": "MissingUpdateAuthority", + "msg": "Missing update authority" } ], "metadata": { diff --git a/programs/mpl-core/src/error.rs b/programs/mpl-core/src/error.rs index 078aae20..8348cdbd 100644 --- a/programs/mpl-core/src/error.rs +++ b/programs/mpl-core/src/error.rs @@ -88,6 +88,10 @@ pub enum MplCoreError { /// 19 - Invalid Collection passed in #[error("Invalid Collection passed in")] InvalidCollection, + + /// 20 - Missing update authority + #[error("Missing update authority")] + MissingUpdateAuthority, } impl PrintProgramError for MplCoreError { diff --git a/programs/mpl-core/src/instruction.rs b/programs/mpl-core/src/instruction.rs index 0b1f8991..369e6637 100644 --- a/programs/mpl-core/src/instruction.rs +++ b/programs/mpl-core/src/instruction.rs @@ -16,11 +16,12 @@ pub enum MplAssetInstruction { /// This function creates the initial Asset, with or without plugins. #[account(0, writable, signer, name="asset_address", desc = "The address of the new asset")] #[account(1, optional, writable, name="collection", desc = "The collection to which the asset belongs")] - #[account(2, optional, name="update_authority", desc = "The authority of the new asset")] + #[account(2, optional, name="authority", desc = "The authority signing for creation")] #[account(3, writable, signer, name="payer", desc = "The account paying for the storage fees")] #[account(4, optional, name="owner", desc = "The owner of the new asset. Defaults to the authority if not present.")] - #[account(5, name="system_program", desc = "The system program")] - #[account(6, optional, name="log_wrapper", desc = "The SPL Noop Program")] + #[account(5, optional, name="update_authority", desc = "The authority on the new asset")] + #[account(6, name="system_program", desc = "The system program")] + #[account(7, optional, name="log_wrapper", desc = "The SPL Noop Program")] Create(CreateArgs), /// Create a new mpl-core Collection. diff --git a/programs/mpl-core/src/processor/create.rs b/programs/mpl-core/src/processor/create.rs index 66ef4b0e..06cb037c 100644 --- a/programs/mpl-core/src/processor/create.rs +++ b/programs/mpl-core/src/processor/create.rs @@ -13,8 +13,6 @@ use crate::{ utils::fetch_core_data, }; -use super::update; - #[repr(C)] #[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug, Clone)] pub struct CreateArgs { diff --git a/programs/mpl-core/src/state/update_authority.rs b/programs/mpl-core/src/state/update_authority.rs index f1208c13..30fb84d7 100644 --- a/programs/mpl-core/src/state/update_authority.rs +++ b/programs/mpl-core/src/state/update_authority.rs @@ -60,17 +60,23 @@ impl UpdateAuthority { let collection = CollectionData::load(collection_info, 0)?; solana_program::msg!("Collection: {:?}", collection); - assert_signer(ctx.payer)?; + let authority = match ctx.authority { + Some(authority) => { + assert_signer(authority)?; + authority + } + None => ctx.payer, + }; let maybe_update_delegate = fetch_plugin(collection_info, PluginType::UpdateDelegate); if let Ok((mut authorities, _, _)) = maybe_update_delegate { authorities.push(Authority::UpdateAuthority); - if assert_collection_authority(&collection, ctx.payer, &authorities).is_err() { + if assert_collection_authority(&collection, authority, &authorities).is_err() { return Ok(ValidationResult::Rejected); } - } else if ctx.payer.key != &collection.update_authority { + } else if authority.key != &collection.update_authority { return Ok(ValidationResult::Rejected); } @@ -118,7 +124,7 @@ impl UpdateAuthority { /// Validate the transfer lifecycle event. pub fn validate_transfer( &self, - ctx: &TransferAccounts, + _ctx: &TransferAccounts, ) -> Result { Ok(ValidationResult::Pass) }