Quantstamp reviewed Neutral Trade on 4 Jul 2025: 12 findings, 0 critical; 6 marked fixed, 6 acknowledged.
Report hosted on certificate.quantstamp.com.
Trustblock does not review code.
Statuses are the security firm’s own, from its report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 0 | 0 | 1 |
| Medium | 0 | 0 | 1 |
| Low | 0 | 6 | 4 |
The `end_distribution()`function resets `left_to_distribute` and `distribution_base_amount` without verifying that the full distribution amount has been transferred to strategies. If the keeper closes the period prematurely, any undistributed balance is silently ignored, leaving some strategies under‑funded, and skewing allocation percentages across strategies.
A user's withdrawal is not priced at the time of their request but at the time of processing. This exposes the user to potentially significant slippage, as processing can be delayed, and the share price can change in the interim. 1- When a user calls `request_withdrawal()`, the protocol only records the amount of shares (e.g., $100) to be withdrawn. The user's shares are not burned at this time. 2- The `process_withdrawal()` instruction, which calculates the asset amount to be withdrawn (`net_redemption_amount`), can be delayed by the `withdrawal_available_timestamp` mechanism. 3- Because the share price is only calculated within `process_withdrawal`, any price drop during the delay will force the user to get less asset amount than they anticipated. This makes the true cost of a withdrawal unpredictable.
The `update_oracle()` bounds each new equity value to `current_equity = (current_equity * oracle_buffer / 100)`. When `oracle_buffer` is set to **100 %**, the integer calculation yields: * **Lower bound:** `0` (‑100 %; equity can be reported as zero) * **Upper bound:** `current_equity * 2` (+100 %; equity cannot exceed 2×) The result is an **asymmetric clamp**: the keeper may drive the bundle’s equity all the way to **zero**, but can never report appreciation beyond a doubling. This allows a compromised keeper to drag the current equity to zero, but never more than the double of the current equity.
The `remove_strategy` instruction fails to close the `strategy_account` PDA after disabling it in the bundle. Instead, it only sets the allowed flag to false. This orphans the on-chain account, making the SOL paid for its rent permanently irrecoverable. Every time a strategy is "removed," the protocol leaks the capital (rent) required to maintain that strategy's account. Over time, this will lead to a significant and irreversible loss of funds for the protocol manager.
Each time a user’s deposit is processed, `last_deposit_timestamp` is overwritten. When that user later calls `request_withdrawal()`, the cooldown is computed from this single, most‑recent timestamp, meaning **all** previously unlocked shares become subject to the full delay again. The design forces long‑term holders to wait unnecessarily if they make small top‑ups, and it encourages dividing assets across multiple accounts to avoid self‑induced lock‑ups.
Users request withdrawals using `request_withdrawal()`, expecting the current fee schedule to apply. However, the fee is not finalised at request time; it is recalculated during `process_withdrawal()` using the live `bundle_account.withdrawal_fee`. The fee can change between these two events, leaving the user charged more (or less) than they had accounted for when submitting the request.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (1)
236 projects reviewed · 332 reports · latest Oct 2026
See Quantstamp’s auditsSomething 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