From d1db9a346789822f386223e41d787b8bb9a16e25 Mon Sep 17 00:00:00 2001 From: CanvasL <746591811@qq.com> Date: Thu, 12 Sep 2024 16:45:09 +0800 Subject: [PATCH] fix: binding check --- .../puppet/programs/puppet/src/errors.rs | 4 ++ .../programs/puppet/src/instructions/bind.rs | 64 +++++++++++++------ .../src/instructions/bind_collection.rs | 22 +++---- .../src/instructions/check_bound_by_device.rs | 8 +-- .../src/instructions/check_bound_by_nft.rs | 4 +- .../src/instructions/get_device_by_nft.rs | 4 +- .../src/instructions/get_nft_by_device.rs | 4 +- .../puppet/src/state/device_binding.rs | 2 +- .../puppet/programs/puppet/src/state/mod.rs | 8 +-- .../state/{nft_binding.rs => mpl_binding.rs} | 4 +- ...n_binding.rs => mpl_collection_binding.rs} | 2 +- extensions/puppet/tests/puppet.ts | 2 +- 12 files changed, 78 insertions(+), 50 deletions(-) rename extensions/puppet/programs/puppet/src/state/{nft_binding.rs => mpl_binding.rs} (53%) rename extensions/puppet/programs/puppet/src/state/{nft_collection_binding.rs => mpl_collection_binding.rs} (73%) diff --git a/extensions/puppet/programs/puppet/src/errors.rs b/extensions/puppet/programs/puppet/src/errors.rs index f559506..71f99a4 100644 --- a/extensions/puppet/programs/puppet/src/errors.rs +++ b/extensions/puppet/programs/puppet/src/errors.rs @@ -31,4 +31,8 @@ pub enum ErrorCode { #[msg("The provided nft does not match the binding.")] NFTDoesNotMatch, + + DeviceAssociatedTokenDoesNotMatch, + + InvalidDeviceMintPDA, } \ No newline at end of file diff --git a/extensions/puppet/programs/puppet/src/instructions/bind.rs b/extensions/puppet/programs/puppet/src/instructions/bind.rs index c079953..4d91409 100644 --- a/extensions/puppet/programs/puppet/src/instructions/bind.rs +++ b/extensions/puppet/programs/puppet/src/instructions/bind.rs @@ -1,6 +1,7 @@ use crate::errors::ErrorCode; -use crate::state::{DeviceBinding, DeviceCollectionBinding, NFTBinding, NFTCollectionBinding}; +use crate::state::{DeviceBinding, DeviceCollectionBinding, MplBinding, MplCollectionBinding}; use anchor_lang::prelude::*; +use anchor_spl::associated_token::get_associated_token_address_with_program_id; use anchor_spl::token::TokenAccount; #[derive(Accounts)] @@ -9,20 +10,19 @@ use anchor_spl::token::TokenAccount; )] pub struct Bind<'info> { #[account( - constraint = nft_account.key() == params.nft, - constraint = nft_account.owner == payer.key() @ ErrorCode::PayerDoesNotOwnNFT + constraint = mpl_associated_token.key() == params.mpl_ata, + constraint = mpl_associated_token.owner == payer.key() @ ErrorCode::PayerDoesNotOwnNFT )] - pub nft_account: Account<'info, TokenAccount>, + pub mpl_associated_token: Account<'info, TokenAccount>, #[account( - constraint = device_account.key() == params.device, - constraint = device_account.owner == payer.key() @ ErrorCode::PayerDoesNotOwnDevice + constraint = device_associated_token.owner == payer.key() @ ErrorCode::PayerDoesNotOwnDevice )] - pub device_account: Account<'info, TokenAccount>, + pub device_associated_token: Account<'info, TokenAccount>, #[account( init_if_needed, payer = payer, space = 8 + 32 + 1, - seeds = [b"device_binding", device_account.key().as_ref()], + seeds = [b"device_binding", device_associated_token.key().as_ref()], bump )] pub device_binding: Account<'info, DeviceBinding>, @@ -30,12 +30,12 @@ pub struct Bind<'info> { init_if_needed, payer = payer, space = 8 + 32 + 1, - seeds = [b"nft_binding", nft_account.key().as_ref()], + seeds = [b"mpl_binding", mpl_associated_token.key().as_ref()], bump )] - pub nft_binding: Account<'info, NFTBinding>, + pub mpl_binding: Account<'info, MplBinding>, pub device_collection_binding: Account<'info, DeviceCollectionBinding>, - pub nft_collection_binding: Account<'info, NFTCollectionBinding>, + pub mpl_collection_binding: Account<'info, MplCollectionBinding>, #[account(mut)] pub payer: Signer<'info>, pub rent: Sysvar<'info, Rent>, @@ -44,40 +44,64 @@ pub struct Bind<'info> { #[derive(AnchorSerialize, AnchorDeserialize, Debug, Clone)] pub struct BindParams { + pub dephy_id_program: Pubkey, pub device: Pubkey, - pub nft: Pubkey, + pub device_mint_bump: u8, + pub mpl_ata: Pubkey, } pub fn bind(ctx: Context, params: BindParams) -> Result<()> { let device_binding = &mut ctx.accounts.device_binding; - let nft_binding = &mut ctx.accounts.nft_binding; + let mpl_binding = &mut ctx.accounts.mpl_binding; + + let device_mint_pubkey = Pubkey::create_program_address( + &[ + b"DePHY_ID-DEVICE", + ctx.accounts.mpl_collection_binding.device_collection.as_ref(), + params.device.as_ref(), + &[params.device_mint_bump], + ], + ¶ms.dephy_id_program, + ).map_err(|_| ErrorCode::InvalidDeviceMintPDA)?; + + let device_ata = get_associated_token_address_with_program_id( + &ctx.accounts.payer.key(), + &device_mint_pubkey, + ¶ms.dephy_id_program, + ); + + require_keys_eq!( + ctx.accounts.device_associated_token.key(), + device_ata, + ErrorCode::DeviceAssociatedTokenDoesNotMatch + ); require_keys_eq!( - ctx.accounts.device_account.mint, - ctx.accounts.nft_collection_binding.device_collection, + ctx.accounts.device_associated_token.mint, + device_mint_pubkey, ErrorCode::DeviceCollectionDoesNotMatch ); require_keys_eq!( - ctx.accounts.nft_account.mint, + ctx.accounts.mpl_associated_token.mint, ctx.accounts.device_collection_binding.nft_collection, ErrorCode::NFTCollectionDoesNotMatch ); require_keys_eq!( - device_binding.nft, + device_binding.mpl_ata, Pubkey::default(), ErrorCode::DeviceAlreadyBound ); require_keys_eq!( - nft_binding.device, + mpl_binding.device_ata, Pubkey::default(), ErrorCode::NFTAlreadyBound ); - device_binding.nft = params.nft; - nft_binding.device = params.device; + device_binding.mpl_ata = params.mpl_ata; + mpl_binding.device_ata = params.device; Ok(()) } diff --git a/extensions/puppet/programs/puppet/src/instructions/bind_collection.rs b/extensions/puppet/programs/puppet/src/instructions/bind_collection.rs index 1e4dfe3..1ce2d7e 100644 --- a/extensions/puppet/programs/puppet/src/instructions/bind_collection.rs +++ b/extensions/puppet/programs/puppet/src/instructions/bind_collection.rs @@ -1,5 +1,5 @@ use crate::errors::ErrorCode; -use crate::state::{DeviceCollectionBinding, NFTCollectionBinding}; +use crate::state::{DeviceCollectionBinding, MplCollectionBinding}; use anchor_lang::prelude::*; use anchor_spl::token::Mint; @@ -10,21 +10,21 @@ use anchor_spl::token::Mint; pub struct BindCollection<'info> { /// CHECK: #[account( - constraint = product_mint_account.key() == params.device_collection, + constraint = product_mint.key() == params.device_collection, seeds = [b"DePHY_ID-PRODUCT", payer.key().as_ref(), params.product_metadata_name.as_ref()], bump = params.product_mint_bump, seeds::program = params.dephy_id_program.key() )] - pub product_mint_account: AccountInfo<'info>, + pub product_mint: AccountInfo<'info>, #[account( - constraint = nft_mint_account.key() == params.nft_collection, + constraint = mpl_mint.key() == params.nft_collection, )] - pub nft_mint_account: Account<'info, Mint>, + pub mpl_mint: Account<'info, Mint>, #[account( init_if_needed, payer = payer, space = 8 + 32 + 1, - seeds = [b"device_collection_binding", product_mint_account.key().as_ref()], + seeds = [b"device_collection_binding", product_mint.key().as_ref()], bump )] pub device_collection_binding: Account<'info, DeviceCollectionBinding>, @@ -32,10 +32,10 @@ pub struct BindCollection<'info> { init_if_needed, payer = payer, space = 8 + 32 + 1, - seeds = [b"nft_collection_binding", nft_mint_account.key().as_ref()], + seeds = [b"mpl_collection_binding", mpl_mint.key().as_ref()], bump )] - pub nft_collection_binding: Account<'info, NFTCollectionBinding>, + pub mpl_collection_binding: Account<'info, MplCollectionBinding>, #[account(mut)] pub payer: Signer<'info>, pub rent: Sysvar<'info, Rent>, @@ -53,7 +53,7 @@ pub struct BindCollectionParams { pub fn bind_collection(ctx: Context, params: BindCollectionParams) -> Result<()> { let device_collection_binding = &mut ctx.accounts.device_collection_binding; - let nft_collection_binding = &mut ctx.accounts.nft_collection_binding; + let mpl_collection_binding = &mut ctx.accounts.mpl_collection_binding; require_keys_eq!( device_collection_binding.nft_collection, @@ -62,13 +62,13 @@ pub fn bind_collection(ctx: Context, params: BindCollectionParam ); require_keys_eq!( - nft_collection_binding.device_collection, + mpl_collection_binding.device_collection, Pubkey::default(), ErrorCode::NFTCollectionAlreadyBound ); device_collection_binding.nft_collection = params.nft_collection; - nft_collection_binding.device_collection = params.device_collection; + mpl_collection_binding.device_collection = params.device_collection; Ok(()) } diff --git a/extensions/puppet/programs/puppet/src/instructions/check_bound_by_device.rs b/extensions/puppet/programs/puppet/src/instructions/check_bound_by_device.rs index ef0ed52..3124299 100644 --- a/extensions/puppet/programs/puppet/src/instructions/check_bound_by_device.rs +++ b/extensions/puppet/programs/puppet/src/instructions/check_bound_by_device.rs @@ -1,16 +1,16 @@ use crate::errors::ErrorCode; -use crate::state::{DeviceBinding, NFTBinding}; +use crate::state::{DeviceBinding, MplBinding}; use anchor_lang::prelude::*; #[derive(Accounts)] pub struct Bound<'info> { pub device_binding: Account<'info, DeviceBinding>, - pub nft_binding: Account<'info, NFTBinding>, + pub mpl_binding: Account<'info, MplBinding>, } pub fn check_bound_by_device(ctx: Context, device: Pubkey) -> Result { - if ctx.accounts.nft_binding.device != device { + if ctx.accounts.mpl_binding.device_ata != device { return Err(ErrorCode::DeviceDoesNotMatch.into()); } - Ok(ctx.accounts.device_binding.nft != Pubkey::default()) + Ok(ctx.accounts.device_binding.mpl_ata != Pubkey::default()) } \ No newline at end of file diff --git a/extensions/puppet/programs/puppet/src/instructions/check_bound_by_nft.rs b/extensions/puppet/programs/puppet/src/instructions/check_bound_by_nft.rs index 08aa238..e56aac6 100644 --- a/extensions/puppet/programs/puppet/src/instructions/check_bound_by_nft.rs +++ b/extensions/puppet/programs/puppet/src/instructions/check_bound_by_nft.rs @@ -3,8 +3,8 @@ use anchor_lang::prelude::*; use super::Bound; pub fn check_bound_by_nft(ctx: Context, nft: Pubkey) -> Result { - if ctx.accounts.device_binding.nft != nft { + if ctx.accounts.device_binding.mpl_ata != nft { return Err(ErrorCode::NFTDoesNotMatch.into()); } - Ok(ctx.accounts.nft_binding.device != Pubkey::default()) + Ok(ctx.accounts.mpl_binding.device_ata != Pubkey::default()) } \ No newline at end of file diff --git a/extensions/puppet/programs/puppet/src/instructions/get_device_by_nft.rs b/extensions/puppet/programs/puppet/src/instructions/get_device_by_nft.rs index 09fb2a2..2ce3223 100644 --- a/extensions/puppet/programs/puppet/src/instructions/get_device_by_nft.rs +++ b/extensions/puppet/programs/puppet/src/instructions/get_device_by_nft.rs @@ -3,8 +3,8 @@ use anchor_lang::prelude::*; use super::Bound; pub fn get_device_by_nft(ctx: Context, nft: Pubkey) -> Result { - if ctx.accounts.device_binding.nft != nft { + if ctx.accounts.device_binding.mpl_ata != nft { return Err(ErrorCode::NFTDoesNotMatch.into()); } - Ok(ctx.accounts.nft_binding.device) + Ok(ctx.accounts.mpl_binding.device_ata) } \ No newline at end of file diff --git a/extensions/puppet/programs/puppet/src/instructions/get_nft_by_device.rs b/extensions/puppet/programs/puppet/src/instructions/get_nft_by_device.rs index 2ccba17..3e8a821 100644 --- a/extensions/puppet/programs/puppet/src/instructions/get_nft_by_device.rs +++ b/extensions/puppet/programs/puppet/src/instructions/get_nft_by_device.rs @@ -3,8 +3,8 @@ use anchor_lang::prelude::*; use super::Bound; pub fn get_nft_by_device(ctx: Context, device: Pubkey) -> Result { - if ctx.accounts.nft_binding.device != device { + if ctx.accounts.mpl_binding.device_ata != device { return Err(ErrorCode::DeviceDoesNotMatch.into()); } - Ok(ctx.accounts.device_binding.nft) + Ok(ctx.accounts.device_binding.mpl_ata) } \ No newline at end of file diff --git a/extensions/puppet/programs/puppet/src/state/device_binding.rs b/extensions/puppet/programs/puppet/src/state/device_binding.rs index 9145745..c8adae9 100644 --- a/extensions/puppet/programs/puppet/src/state/device_binding.rs +++ b/extensions/puppet/programs/puppet/src/state/device_binding.rs @@ -2,6 +2,6 @@ use anchor_lang::prelude::*; #[account] pub struct DeviceBinding { - pub nft: Pubkey, + pub mpl_ata: Pubkey, pub bump: u8, } diff --git a/extensions/puppet/programs/puppet/src/state/mod.rs b/extensions/puppet/programs/puppet/src/state/mod.rs index 77f483e..66e32d9 100644 --- a/extensions/puppet/programs/puppet/src/state/mod.rs +++ b/extensions/puppet/programs/puppet/src/state/mod.rs @@ -1,9 +1,9 @@ pub mod device_collection_binding; -pub mod nft_collection_binding; +pub mod mpl_collection_binding; pub mod device_binding; -pub mod nft_binding; +pub mod mpl_binding; pub use device_collection_binding::*; -pub use nft_collection_binding::*; +pub use mpl_collection_binding::*; pub use device_binding::*; -pub use nft_binding::*; \ No newline at end of file +pub use mpl_binding::*; \ No newline at end of file diff --git a/extensions/puppet/programs/puppet/src/state/nft_binding.rs b/extensions/puppet/programs/puppet/src/state/mpl_binding.rs similarity index 53% rename from extensions/puppet/programs/puppet/src/state/nft_binding.rs rename to extensions/puppet/programs/puppet/src/state/mpl_binding.rs index 9c128ae..cd84b2e 100644 --- a/extensions/puppet/programs/puppet/src/state/nft_binding.rs +++ b/extensions/puppet/programs/puppet/src/state/mpl_binding.rs @@ -1,7 +1,7 @@ use anchor_lang::prelude::*; #[account] -pub struct NFTBinding { - pub device: Pubkey, +pub struct MplBinding { + pub device_ata: Pubkey, pub bump: u8, } diff --git a/extensions/puppet/programs/puppet/src/state/nft_collection_binding.rs b/extensions/puppet/programs/puppet/src/state/mpl_collection_binding.rs similarity index 73% rename from extensions/puppet/programs/puppet/src/state/nft_collection_binding.rs rename to extensions/puppet/programs/puppet/src/state/mpl_collection_binding.rs index c7796b0..e800d64 100644 --- a/extensions/puppet/programs/puppet/src/state/nft_collection_binding.rs +++ b/extensions/puppet/programs/puppet/src/state/mpl_collection_binding.rs @@ -1,7 +1,7 @@ use anchor_lang::prelude::*; #[account] -pub struct NFTCollectionBinding { +pub struct MplCollectionBinding { pub device_collection: Pubkey, pub bump: u8, } diff --git a/extensions/puppet/tests/puppet.ts b/extensions/puppet/tests/puppet.ts index c19aa5b..aa3ebb2 100644 --- a/extensions/puppet/tests/puppet.ts +++ b/extensions/puppet/tests/puppet.ts @@ -70,7 +70,7 @@ describe("puppet program", () => { ); const [nftBindingPubkey] = PublicKey.findProgramAddressSync( - [Buffer.from("nft_binding"), nftAccount.toBuffer()], + [Buffer.from("mpl_binding"), nftAccount.toBuffer()], program.programId );