sherlock-audit / 2024-09-orderly-network-solana-contract-judging

0 stars 0 forks source link

Droll Cider Armadillo - reset_vault.rs and reinit_vault.rs does not work as intended #114

Open sherlock-admin2 opened 4 days ago

sherlock-admin2 commented 4 days ago

Droll Cider Armadillo

Medium

reset_vault.rs and reinit_vault.rs does not work as intended

Summary

When reset_vault.apply() is called, the ownership of the vault authority program is given back to the system and the space in vault authority is set to zero.

When that happens, it is not possible to reinit() the vault since the ownership is currently the Solana System Program. Also, there is no reallocation of required space when reinitializing the vault.

Root Cause

In ResetVault, the vault_authority is assigned to the system and the data space is reduced to zero:

impl ResetVault<'_> {
    pub fn apply(ctx: &mut Context<ResetVault>) -> Result<()> {
        let vault_authority = &mut ctx.accounts.vault_authority.to_account_info();
>       vault_authority.assign(&system_program::ID);
>       vault_authority.realloc(0, false)?;
        msg!("Reset OApp");
        Ok(())
    }
}

In reinit_vault.rs, the function apply() attempts to reinitialize the existing vault_authority.

impl ReinitVault<'_> {
    pub fn apply(
        ctx: &mut Context<ReinitVault>,
        reset_oapp_params: &ReinitVaultParams,
    ) -> Result<()> {
        let vault_authority = &mut ctx.accounts.vault_authority;
        vault_authority.owner = reset_oapp_params.owner;
        vault_authority.dst_eid = reset_oapp_params.dst_eid;
        vault_authority.deposit_nonce = reset_oapp_params.deposit_nonce;
        vault_authority.order_delivery = reset_oapp_params.order_delivery;
        vault_authority.inbound_nonce = reset_oapp_params.inbound_nonce;
        vault_authority.sol_chain_id = reset_oapp_params.sol_chain_id;
        vault_authority.bump = ctx.bumps.vault_authority;
        Ok(())
    }
}

This will not work for two reasons.

  1. The ownership of vault_authority is already the Solana System Program
  2. The vault is already initialized, but there is no storage space give to the reinitialization.

For reference, this is how delete_account() works in the Solana program. The account is sent to the system and the data size is set to zero. This account cannot be retrieved and reinitialized.

/// Helper function to totally delete an account on-chain
#[cfg(target_os = "solana")]
fn delete_account(account_info: &AccountInfo) -> Result<(), ProgramError> {
    account_info.assign(&system_program::id());
    account_info.realloc(0, false)
}

Internal pre-conditions

No response

External pre-conditions

No response

Attack Path

No response

Impact

reset_vault and reinit_vault does not work.

PoC

No response

Mitigation

  1. Remove the assign line to transfer of ownership to Solana system program.
  2. When calling reinit.apply, reallocate space for the vault:
impl ReinitVault<'_> {
    pub fn apply(
        ctx: &mut Context<ReinitVault>,
        reset_oapp_params: &ReinitVaultParams,
    ) -> Result<()> {
        let vault_authority = &mut ctx.accounts.vault_authority.to_account_info();

        // Reallocate space
        vault_authority.realloc(8 + VaultAuthority::INIT_SPACE, false)?;