Let's say I have a PDA which maintains the global state of my program. This is like a singleton. And the following snippets of code initialize it :
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
require!(
!ctx.accounts.global.initialized,
ErrorCodes::AlreadyInitialized
);
ctx.accounts.global.authority = *ctx.accounts.user.key;
ctx.accounts.global.initialized = true;
Ok(())
}
And here is the accounts struct:
#[account]
pub struct Global {
pub authority: Pubkey,
pub initialized: bool,
pub some_things_here: bool;
}
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(init, payer = user, space = 8+1+1, seeds = [b"global"], bump)]
pub global: Account<'info, Global>,
#[account(mut)]
pub user: Signer<'info>,
pub system_program: Program<'info, System>,
}
It is entirely possible that somebody could frontrun the initialization. For example:
- Deploy the program
- Attacker calls
initialize
before the honest admin can callinitialize
- Now the attacker has full control and is the
authority
How can I prevent this attack (I'm using anchor)? Does there exist a best practice?