Parity Finance Liquid Staking & Early Purchase security record

As of 30 Oct 2026, Parity Finance Liquid Staking & Early Purchase has 2 audit reports by 1 security firm on Trustblock; the latest is by Quantstamp, dated 3 Jun 2025. Those reports list no open critical findings.

Critical findings
No open critical findings
Across 2 reports.
Open the latest report
Your label, live
Get the label for your site

Record last updated . It holds audits and findings, contracts and incidents up to Oct 2026. Trustblock does not review code.

Audits2

Newest first

AuditSecurity firmDateScopeCritical findingsReport
Parity Finance Liquid Staking & Early PurchaseSecurity firm: QuantstampDate: Scope: Files named in the reportNo open critical findingsOpen · certificate.quantstamp.com
Parity FinanceSecurity firm: QuantstampDate: Scope: Repository at commit 9eee7b5No open critical findingsOpen · certificate.quantstamp.com

Findings40

Statuses are the security firm’s own, from each report.

SeverityOpenAcknowledgedFixed
Critical000
High006
Medium208
Low8115
HighBase Tokens Are Not Transferred Out After Restaking Expired WithdrawalsParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

The `liquid_staking::restake_expired_withdrawal::handler()` function restakes the expired withdrawals by minting LST tokens back to the stakers. However, it does not transfer the relevant user's base tokens (funded by the depositor) from the `window_base_token_account` to the `pair_base_token_account`. Therefore, these base tokens will remain locked in the `window_base_token_account`, preventing the closing of the `withdrawal_window` in the `liquid_staking::close_withdrawal_window::handler()` function.

Open the report
HighCollected Payments Remain Locked in the Sale AccountParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

During the token purchase phase in the `early-purchase` program, buyers transfer their payments (either SPL tokens to the `sale_payment_ata` or SOL directly to the Sale PDA). The sale organizer (acting through a Guardian) deposits the `sale.purchase_mint` tokens for distribution after the sale ends. However, the program lacks a mechanism to transfer the collected buyer payments from the `Sale` PDA and ATA accounts to the sale organizer or a designated treasury. It is also noted that the address of the user initiating the sale is not saved in the `Sale` PDA, and only guardians with `deposit_tokens` permission can deposit the `sale.purchase_mint` tokens.

Open the report
HighIncorrect Amount Transferred During Token DepositsParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

The  `early_purchase::deposit_tokens::handler()` function is intended to enable a Guardian to deposit a specified quantity of `purchase_mint` tokens (`params.amount_to_deposit`) into the sale token vault  `sale_purchase_ata`. However, the `token::transfer` CPI within this instruction incorrectly uses `sale.calculate_base_purchase_cost(amount_to_deposit)` as the amount argument for the transfer instead of the `amount_to_deposit`, resulting in a significantly different value: ```rust token::transfer( CpiContext::new( purchase_program.to_account_info(), token::Transfer { from: authority_purchase_ata.to_account_info(), to: sale_purchase_ata.to_account_info(), authority: authority.to_account_info(), }, ), sale.calculate_base_purchase_cost(amount_to_deposit), ) ```

Open the report
HighIncorrect Authority Used for Token Transfer Prevents All RedemptionsParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

The `early_purchase::redeem_receipt::handler()` function is responsible for transferring the `purchase_mint` tokens from the sale's ATA (`config_purchase_ata`) to the buyer's ATA (`buyer_purchase_ata`) during sale receipt redemption. However, the `token::transfer` CPI is incorrectly configured with the `buyer` as the authority for this transfer: ```rust token::transfer( CpiContext::new( purchase_program.to_account_info(), token::Transfer { from: config_purchase_ata.to_account_info(), to: buyer_purchase_ata.to_account_info(), authority: buyer.to_account_info(), }, ), num_tokens_pending, ) ```

Open the report
HighMissing/limited Test Suite in Early Purchase ProgramParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

The Early Purchase program appears to be completly missing a test suite. Contracts that are not extensively tested are at high risk of serious bugs that can impact the protocol's proper functioning and security. While audits can help developers to find bugs, they are not a substitute for thorough unit and integration testing.

Open the report
HighTokens Can Be Redeemed From Any SaleParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

Sale accounts can be created by any user and they are assigned as their admins. Additionally, receipt PDAs are derived with the following seeds at the buyer's first token purchase: ``` seeds = [ Receipt::PREFIX.as_bytes(), &buyer.key.to_bytes() ] ``` This implies that `Receipt` accounts are initialized in a 1:1 relation to buyer accounts, allowing an attacker to create a receipt and purchase an amount of a worthless token and redeem the receipt against a sale that holds actual, legitimate tokens.

Open the report
MediumGuardians Can Prematurely End a SaleParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

The `early_purchase::end_sale::handler()`function is used by a guardian to end a specific sale. However, the this function does not check that the referenced sale end time has passed (`sale.is_end_time_reached()`), allowing guardians to end any sale even before it has officially ended.

Open the report
MediumImproper Space Allocation for `PDA` InitializationParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

The instructions that initialize PDAs in the `early-purchase` program use the `space` parameter (`#[account(init, payer = ..., space = ...)]`) to specify the space needed for account creation. The `space` attribute expects the total space required for the account's data, including an 8-byte discriminator. However, the 8-byte discriminator is not accounted for in the size calculation. If insufficient space is allocated, it could lead to runtime errors during account initialization or data serialization issues later if data attempts to write past the allocated boundary.

Open the report
MediumLack of Slippage ProtectionParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

When users purchase tokens in the `early-purchase` program using SOL, the current SOL price is determined dynamically at the time of transaction execution using a Pyth Network oracle price feed. However, the current token purchase implementation does not allow users to specify a maximum amount of SOL they are willing to pay for their desired quantity of purchase tokens, only the number of tokens to buy. While the `sale.max_price_feed_age` check ensures the oracle price is not excessively stale, it does not protect against legitimate, recent price volatility that occurs before transaction confirmation. The `sale.purchase_mint` token price (`sale.payment_amount`) may also change without the buyer's knowledge.

Open the report
MediumOngoing or Imminent Sales Can Be Arbitrarily UpdatedParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

The `early_purchase::update_sale::handler()` function permits `Guardians` with `update_sale` permissions to modify critical parameters such as `sale.purchase_mint`, `sale.payment_mint`, `sale.guard_purchases` and so on, even if the `sale.is_start_time_reached()`is `true`. Buyers typically make purchase decisions based on the observed state of the sale. If these parameters can be altered while the sale is active or just moments before a buyer's transaction is processed, a buyer might inadvertently pay a different price (potentially higher) or face different purchasing conditions than they initially expected. The `purchase_tokens` instruction calculates the cost dynamically at the time of execution based on the current `Sale` state. This could lead to user frustration, loss of trust, and scenarios where buyers feel deceived if, for instance, the token price effectively increases due to a mid-sale update.

Open the report
Show 10 more
MediumSales Cannot Be FrozenParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

`Sale` accounts are supposedly freezable by guardians/admins as they have an `is_frozen()` function that checks if `self.state == SaleState::Frozen`, which is called in the `PurchaseTokens` instruction handler. However there is no mechanism allowing authority to freeze and unfreeze sales as no instruction implements such a logic.

Open the report
MediumStrict Token Balance Check in `close_withdrawal_window` Creates a Denial of Service RiskParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

A malicious user may transfer a few base tokens directly to a `window_base_token_account` of the `liquid-staking` program, preventing the `window_authority` to closing the ATA because of the following strict check: ```rust require!( window_base_token_account.amount == 0, StakingError::WindowHasActiveRequests ); ```

Open the report
MediumUnrestricted Sale Creation Can Result in Denial of Service AttackParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

The `early_purchase::initialize_sale::handler()` function allows any user to create a new `Sale`. However, it does not implement any fee or significant disincentive beyond standard Solana transaction costs and account rent. This open and low-cost sale creation mechanism that can be exploited by malicious actors to spam the platform by creating a large number of sales or create sales with malicious properties.

Open the report
MediumState-Account Balance Discrepancies in Token ManagementParity Finance · Quantstamp · 27 Sep 2024Fixed

The `parity-issuance` and `parity-staking` programs effectively track certain token-related changes locally in state variables such as `total_collateral` and `base_balance`. While there is nothing inherently wrong with tracking these values for program logic, they should not be relied upon as the authoritative source of truth for the actual token balances in vault accounts. Discrepancies may occur because users can transfer tokens directly to vaults, resulting in a mismatch between the tracked state and the actual vault balance. For example: 1. **`deposit_funds.rs` and `withdraw_funds.rs`**: The `total_collateral` field is updated locally in the `token_manager` account, but this value may diverge from the actual vault balance if tokens are transferred directly to the vault. 2. **`unstake.rs`**: The `base_balance` field in the `pool_manager` account is updated via a local variable, but it may not accurately reflect the true balance of the vault. 3. **`initialize_withdraw_funds.rs`**: Withdrawal validations are performed using the stored `total_collateral` value instead of the actual balance in the token account. While local state tracking is beneficial for efficiency and logic within the program, it is important to recognize that these values do not always reflect the real-time balance of vaults and should not be considered definitive for account balances.

Open the report
Low`minimum_deposit` < `deposit_cap` Is Not EnforcedParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

In `liquid_staking::create_pair::handler()` function and `liquid_staking::update_pair_limits::handler()` are missing the validations that ensure `minimum_deposit < deposit_cap`.

Open the report
LowConfig Can Be Initialized by AnyoneParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

No checks exist to enforce that the signer initializing the config is a specific pre-determined address. This allows anyone to initialize the config and takeover its control.

Open the report
LowEarly Purchase Guardian Authority Cannot Be Migrated to a New Pubkey After InitializationParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

The `early_purchase::initialize_guardian::handler()` function allows an admin to create a new Guardian account, but provides no mechanism to update the `authority` Pubkey once set. This creates a significant risk if guardian credentials are compromised or need to be rotated. This is because the `update_guardian` instruction only enables updating the `permissions` but not the `authority`. Additionally, the `GuardianPermissions::manage_guardians` permission exists in the codebase but remains unused, suggesting an incomplete implementation of guardian management functionality.

Open the report
LowImproper Yield ValidationParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

The `liquid_staking::create_pair::handler()` function does not validate the `interval_apr_rate` value, and the current check in the `liquid_staking::update_pair_yield::handler()` only prevents setting the `interval_apr_rate` value to zero. The improper validations allow setting non-positive yield rate values because the rate is adjusted with `PRECISION` (`1e12`) in the exchange rate calculations. The `liquid_staking::create_pair::handler()` function does not limit the maximum value of `interval_apr_rate`, the `MAX_INTERVAL_APR_RATE` is only enforced in the `instructions::update_pair_yield::handler()` function.

Open the report
LowIncorrect Minimum and Excess Deposit Checks in `LST` SwapsParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

The `liquid_staking::swap_lst::handler()` function enables holders of one LST to swap it for a different LST. However the function call on the `destination_pair` that checks if the deposit is too large incorrectly passes zero for the `base_token_amount` field of the function `destination_pair.check_excessive_deposit(quote_amount, base_token_amount)`. Moreover, it lacks a check to validate the the deposit meets the minimum bar via `check_minimum_deposit()`.

Open the report
LowMissing Instruction to Update `max_price_feed_age`Parity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

The `early_purchase::initialize_sale::handler()` function accepts a `max_price_feed_age` parameter that determines the maximum allowable staleness of price feed data. However, once set, this critical parameter cannot be modified. If an administrator configures this value incorrectly during initialization, there is no mechanism available to correct it, potentially leading to permanent operational issues with price feed validation.

Open the report
Show 9 more
LowMissing Upper Limit for Liquid Staking Fees May Be Prohibitive to UsersParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

The `liquid_staking::update_pair_limits::handler()`function creates a pair and takes in a `CreatePairParams` struct instance that holds the `stake_fee_bps`, `swap_fee_bps`, and `withdraw_fee_bps` values. The fee percentage BPS values ​​can be set up to 10000, allowing the program to be configured with a 100% fee percentage.

Open the report
LowMissing Validation Can Lead to Duplicate Guardians in `AccessControl` Compromising Security RedundancyParity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

In `liquid_staking::manage_guardian::handler()`function, an `unseal_authority` can add or remove guardians from the `AccessControl` Account. While the `AccessControl` account supports adding up to five guardians for security redundancy, the implementation lacks duplicate checking for each guardian `Pubkey`. This oversight allows the same guardian `Pubkey` to be added multiple times, potentially compromising the intended redundancy if multiple or all five guardian slots contain identical keys.

Open the report
LowUnsealing Is Not Verified in `create_token_metadata`Parity Finance Liquid Staking & Early Purchase · Quantstamp · 3 Jun 2025Fixed

The `liquid_staking::create_token_metadata::handler()` function does not call `access_control.verify_unsealed()?;`, preventing the guardians from sealing the function in case of emergency.

Open the report
LowDouble Accounting in Current Slot VolumeParity Finance · Quantstamp · 27 Sep 2024Fixed

When a new slot is encountered, the `current_slot_volume` is updated twice: once in the `check_block_limit` function and again at the end of the handler function. This could lead to incorrect accounting of the current slot volume.

Open the report
LowInconsistent Admin Authority Checks in Token Management FunctionsParity Finance · Quantstamp · 27 Sep 2024Fixed

Several token management functions in the parity-issuance program exhibit inconsistencies between the implemented admin checks and the documented behavior. Specifically, these functions are using `token_manager.owner` for admin verification, while the documentation states that `token_manager.admin` should be responsible for these operations. This discrepancy affects the following functions: 1. Adding gatekeepers 2. Removing gatekeepers 3. Updating token manager admin

Open the report
LowInsufficient Input Validation Across Multiple Contract FunctionsParity Finance · Quantstamp · 27 Sep 2024Fixed

Several functions across the parity-contracts codebase lack comprehensive input validation for critical parameters. This includes missing checks for non-zero values, absence of bounds validation for numerical inputs such as fees, and lack of verification for account authorities and states. The affected areas span various operations such as staking, unstaking, minting, configuration updates, and token management. Several explicit examples: 1. `parity_staking` doesn't check if the quantity is 0 in the following functions 1. `stake()` 2. `unstake()` 2. `pt_staking` doesn't check if the quantity is 0 in the following functions 1. `pt_stake()` 2. `pt_unstake()` 3. `parity_issuance` doesn't check if the quantity is 0 in the following functions: 1. `deposit_funds()` 2. `withdraw_funds()` 3. `mint_admin()` 4. `mint()` 5. `redeem()`

Open the report
LowMissing Validation of Mint AddressParity Finance · Quantstamp · 27 Sep 2024Fixed

The `mint` account in the `WithdrawFunds` struct lacks proper validation of its address. This allows an admin to pass in any mint account with an inflated supply, potentially bypassing withdrawal limits.

Open the report
LowOverwriting Pending Withdrawal AmountParity Finance · Quantstamp · 27 Sep 2024Fixed

If a withdrawal is initiated twice before the first one is processed, the second one would overwrite the first one's pending withdrawal amount.

Open the report
LowPotential Inconsistency in Deposit Cap UpdateParity Finance · Quantstamp · 27 Sep 2024Fixed

The `new_deposit_cap` can be set to a value less than the existing deposit amount in the vault account, potentially leading to inconsistencies.

Open the report

Contracts

No deployed address is recorded for these audits.

The reports name a repository or files. Open a report to see its scope.

The repositories and files the reports name

Show this on your site

Is this your project? Show this record on your own website. The label states what the record holds, links to this page and updates by itself. It is free and needs no sign-in.

Content

Facts

Automatic: the three strongest facts of this project’s own record (its last audit and two more), highlighted. They update with the record. Picking a fact turns Automatic off.

Fixed as
Language

Style

Layout
Theme
Accent
Corners

Format

Size
Date
Embed as
HTML
<head>
<script src="https://widget.trustblock.run/project-widget.min.js" defer></script>
</head>
<body>
<div
data-tb-project-widget
data-tb-project-slug="parity-finance-liquid-staking-early-purchase"
></div>
</body>

Paste the code where the label should appear. It uses no API credit and updates by itself.

Something wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.

Tell us