Sealevel Attacks
Sandwich
Background
In some cases, you want to ensure your instructions aren't accompanied by other unexpected ones.
For example, if you want to close an account, you want to ensure that no instruction after you close it is reopneing it.
We'll show a simple example how to allow only specific programs to accompany an instruction.
- For ease of use we use Allowed
PDA
with no constraints on theSigner
, in a realprogram
will need to have a more strict mechanism to set the allowedprograms
.
One Instruction Only
Here we allow only the current instruction
to be executed.
We're confirming both that our instruction
index
is 0
and that we only have 1
instructions
in total.
We start by passing the instructions account.
#[account(address = sysvar::instructions::id())]
instruction_sysvar_account: AccountInfo<'info>,
Extracting the current instruction
index
.
let current_index = load_current_index_checked(&instruction_sysvar_account)?;
Next we extract the total number of instructions
.
read_u16(&mut current, &**data)
And finally we assert both requirements.
require!(current_index == 0, Errors::ExpectedInstructionToBeZero);
require!(num_instructions == 1, Errors::ExpectedOnlyOneInstruction);
Allowed Only
Here we iterate all the instructions
being passed and check each is included in allowed
programs
.
We start by extracting the number of total instructions
.
read_u16(&mut current, &**data)
Next, we iterate all the instructions
.
for index in 0..num_instructions
For each instruction
we assert that it's in our allowed
programs
.
if !allowed.allowed.contains(&instruction.program_id) {
return Err(Errors::ProgramNotAllowed.into());
}