Assessment reports>MultiGov>Discussion>Precarious associated-token-account constraints

Precarious associated-token-account constraints

It was noted during the audit that a few of the instruction contexts had used constraint practices that were considered precarious. Take the TransferVesting instruction context, which involves a VestingBalance account, a current and new Vesting account, and a current and new vester associated token account, as well as a signature of the vester. It is imperative that constraints are present that enforce that the signer owns the vesting TokenAccount, the associated Vesting account, and the VestingBalance account. If any of these constraints are not held, then an attacker might be able to pass a victim's VestingBalance, rather than their own.

Part of our conclusion that the design of this instruction context was precarious was the pattern repeated throughout the codebase where associated token accounts (ATAs) used their own fields as constraints. This then requires other accounts to step in and provide constraints to tie permissions together.

Here is an example:

#[account(
    mut,
    associated_token::mint = mint,
    associated_token::authority = vester_ta.owner,
    associated_token::token_program = token_program
)]
vester_ta: Box<InterfaceAccount<'info, TokenAccount>>,

It is recommended that if an appropriate ATA authority is available it be used as a constraint instead of the ATA itself.

Zellic © 2025Back to top ↑