0

How can I restrict who can call my program instruction in anchor? Suppose I have an instruction that let users to create and delete posts. Trivially I want to grant deletion permission only to the owner of a post (who originally have created it). How can I implement such validation for deletion?

#[program]
pub mod post {
    use super::*;
    pub fn create_post(ctx: Context<CreatePost>, content: String, id: u64) -> Result<()> {
        Ok(())
    }
    pub fn delete_post(ctx: Context<DeletePost>, id: u64) -> Result<()> {
        Ok(())
    }
}

#[derive(Accounts)]
pub struct CreatePost<'info> {
    #[account(mut)]
    pub author: Signer<'info>,
    #[account()]
    pub post_pda: Account<'info, PostPDA>
}

#[derive(accounts)]
pub struct DeletePost<'info> {
    #[account]
    pub author: Signer<'info>
}

#[account]
pub struct PostPDA {
    pub id: u64,
    pub content: String
}

1 Answer 1

4

You'd have to make an extra field for the owner in your PostPDA account and set it in the create_post_instruction. That would look like:

pub fn create_post(ctx: Context<CreatePost>, content: String, id: u64) -> Result<()> {
    ctx.accounts.post_pda.author = ctx.accounts.author.key();
    Ok(())
}


#[account]
pub struct PostPDA {
    pub id: u64,
    pub content: String,
    pub author: Pubkey,
}

Then, subsequent instructions can just check that the author is a signer for that instruction. For example:

#[derive(accounts)]
pub struct DeletePost<'info> {
    #[account]
    pub author: Signer<'info>,
    #[account(has_one = author)]
    pub post_pda: Account<'info, PostPDA>,
}

The has_one = author constraint checks that the author key is the same as the one saved in the post_pda account. This, in conjunction with the Signer constraint on author, guarantees that this instruction only completes successfully if the post_pda author's signature is present.

6
  • Here in ctx.accounts.post_pda.owner = ctx.accounts.author.key(); by owner you mean the author field? Right? Commented Jan 17 at 6:54
  • 1
    Good catch. Thanks!
    – Ademola
    Commented Jan 17 at 7:31
  • Do the author field in the DeletePost and author field in the PostPDA have to be the same? Commented Jan 17 at 20:13
  • 1
    Yh. That's the important part that actually establishes secure deletion! They have to be the same for the instruction to succeed. The has_one constraint enforces that the author account that is a signer in the DeletePost instruction is the same as the PostPDA's author.
    – Ademola
    Commented Jan 17 at 23:00
  • 1
    Yh. This is required for the has_one constraint. has_one = author in this case desugars into constraint = post_pda.author == author.key(). However, if the field is named differently in the post_pda account(say for example owner), then you can still make the same check with constraint = post_pda.owner == author.key().
    – Ademola
    Commented Jan 18 at 16:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.