diff --git a/clients/js/src/generated/instructions/burnV1.ts b/clients/js/src/generated/instructions/burnV1.ts index 32cc9490..f4c7bec0 100644 --- a/clients/js/src/generated/instructions/burnV1.ts +++ b/clients/js/src/generated/instructions/burnV1.ts @@ -114,7 +114,7 @@ export function burnV1( }, authority: { index: 3, - isWritable: true as boolean, + isWritable: false as boolean, value: input.authority ?? null, }, systemProgram: { diff --git a/clients/js/test/burn.test.ts b/clients/js/test/burn.test.ts index d1c314de..89c4dd89 100644 --- a/clients/js/test/burn.test.ts +++ b/clients/js/test/burn.test.ts @@ -264,3 +264,33 @@ test('it cannot burn an asset with the wrong collection specified', async (t) => await t.throwsAsync(result, { name: 'InvalidCollection' }); }); + +test('it can burn asset with different payer', async (t) => { + const umi = await createUmi(); + const owner = await generateSignerWithSol(umi); + const asset = await createAsset(umi, { + owner: owner.publicKey, + }); + await assertAsset(t, umi, { + ...DEFAULT_ASSET, + asset: asset.publicKey, + owner: owner.publicKey, + updateAuthority: { type: 'Address', address: umi.identity.publicKey }, + }); + + const lamportsBefore = await umi.rpc.getBalance(umi.identity.publicKey); + + await burnV1(umi, { + asset: asset.publicKey, + payer: umi.identity, + authority: owner, + }).sendAndConfirm(umi); + + // And the asset address still exists but was resized to 1. + const afterAsset = await assertBurned(t, umi, asset.publicKey); + t.deepEqual(afterAsset.lamports, sol(0.00089784 + 0.0015)); + + const lamportsAfter = await umi.rpc.getBalance(umi.identity.publicKey); + + t.true(lamportsAfter.basisPoints > lamportsBefore.basisPoints); +}); diff --git a/clients/rust/src/generated/instructions/burn_v1.rs b/clients/rust/src/generated/instructions/burn_v1.rs index ca904d32..a58d762b 100644 --- a/clients/rust/src/generated/instructions/burn_v1.rs +++ b/clients/rust/src/generated/instructions/burn_v1.rs @@ -58,7 +58,7 @@ impl BurnV1 { self.payer, true, )); if let Some(authority) = self.authority { - accounts.push(solana_program::instruction::AccountMeta::new( + accounts.push(solana_program::instruction::AccountMeta::new_readonly( authority, true, )); } else { @@ -129,7 +129,7 @@ pub struct BurnV1InstructionArgs { /// 0. `[writable]` asset /// 1. `[writable, optional]` collection /// 2. `[writable, signer]` payer -/// 3. `[writable, signer, optional]` authority +/// 3. `[signer, optional]` authority /// 4. `[optional]` system_program /// 5. `[optional]` log_wrapper #[derive(Default)] @@ -343,7 +343,7 @@ impl<'a, 'b> BurnV1Cpi<'a, 'b> { true, )); if let Some(authority) = self.authority { - accounts.push(solana_program::instruction::AccountMeta::new( + accounts.push(solana_program::instruction::AccountMeta::new_readonly( *authority.key, true, )); @@ -426,7 +426,7 @@ impl<'a, 'b> BurnV1Cpi<'a, 'b> { /// 0. `[writable]` asset /// 1. `[writable, optional]` collection /// 2. `[writable, signer]` payer -/// 3. `[writable, signer, optional]` authority +/// 3. `[signer, optional]` authority /// 4. `[optional]` system_program /// 5. `[optional]` log_wrapper pub struct BurnV1CpiBuilder<'a, 'b> { diff --git a/idls/mpl_core.json b/idls/mpl_core.json index 743d25dc..d775c7a4 100644 --- a/idls/mpl_core.json +++ b/idls/mpl_core.json @@ -803,7 +803,7 @@ }, { "name": "authority", - "isMut": true, + "isMut": false, "isSigner": true, "isOptional": true, "docs": [ diff --git a/programs/mpl-core/src/instruction.rs b/programs/mpl-core/src/instruction.rs index 5cb980f5..4ee1dffa 100644 --- a/programs/mpl-core/src/instruction.rs +++ b/programs/mpl-core/src/instruction.rs @@ -128,7 +128,7 @@ pub(crate) enum MplAssetInstruction { #[account(0, writable, name="asset", desc = "The address of the asset")] #[account(1, optional, writable, name="collection", desc = "The collection to which the asset belongs")] #[account(2, writable, signer, name="payer", desc = "The account paying for the storage fees")] - #[account(3, optional, writable, signer, name="authority", desc = "The owner or delegate of the asset")] + #[account(3, optional, signer, name="authority", desc = "The owner or delegate of the asset")] #[account(4, optional, name="system_program", desc = "The system program")] #[account(5, optional, name="log_wrapper", desc = "The SPL Noop Program")] BurnV1(BurnV1Args), diff --git a/programs/mpl-core/src/processor/burn.rs b/programs/mpl-core/src/processor/burn.rs index 2e78c4cb..5948bead 100644 --- a/programs/mpl-core/src/processor/burn.rs +++ b/programs/mpl-core/src/processor/burn.rs @@ -101,7 +101,7 @@ pub(crate) fn burn<'a>(accounts: &'a [AccountInfo<'a>], args: BurnV1Args) -> Pro Some(HookableLifecycleEvent::Burn), )?; - process_burn(ctx.accounts.asset, authority)?; + process_burn(ctx.accounts.asset, ctx.accounts.payer)?; if let Some(mut collection) = collection { collection.decrement()?; collection.save(ctx.accounts.collection.unwrap(), 0)?; @@ -146,7 +146,7 @@ pub(crate) fn burn_collection<'a>( Some(HookableLifecycleEvent::Burn), )?; - process_burn(ctx.accounts.collection, authority) + process_burn(ctx.accounts.collection, ctx.accounts.payer) } fn process_burn<'a>(core_info: &AccountInfo<'a>, authority: &AccountInfo<'a>) -> ProgramResult {