Fragmetric Restaking Program

QuantstampFiles named in the report

Quantstamp reviewed Fragmetric Restaking Program on 1 Nov 2024: 17 findings, 0 critical; 4 marked fixed, 12 acknowledged, 1 open.

No open critical findings
Open the reportOpen Fragmetric Restaking Program’s security record

Report hosted on certificate.quantstamp.com.

Trustblock does not review code.

Findings17

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

SeverityOpenAcknowledgedFixed
Critical000
High002
Medium111
Low0111
MediumUsers may Not Be Able to WithdrawAcknowledged

The function `check_withdrawal_enabled()` checks for the boolean flag `withdrawal_enabled_flag` that can be set by the admin. The flag determines if users are allowed to call the `request_withdrawal()` function. However, the flag is also checked during the final call to `withdraw()`, when users can withdraw the amount they requested after the batch is processed. This means that if the flag is set to true, users will not be able to call the function `withdraw()` even if they have an already processed amount they can claim.

LowAdmin Can Set Arbitrary Withdrawal Fee RateAcknowledged

The admin has the ability to set a withdrawal fee rate. This value is stored in basis points, which means that a rate of `1` is equal to a 0.01% fee. There are no restrictions on the value the admin can set. This includes the ability to set withdrawal rates above 100% which would block withdrawals. In order to make users feel more secure and prevent the admin from disabling withdrawals via the rate, it is recommended to enforce a maximum allowed rate.

LowData Used for Events Should Be ClarifiedAcknowledged

1. In `user_fund_supported_token_context.rs`, function `deposit_supported_token()`, when emitting the event `UserDepositedSupportedTokenToFund`, it should be clarified if `fund_account` should be created with the values of `receipt_token_price` and `receipt_token_total_supply` before or after the deposit is recorded. 2. In `user_fund_context.rs`, function `deposit_sol()`, when emitting the event `UserDepositedSOLToFund`, it should be clarified if `fund_account` should be created with the values of `receipt_token_price` and `receipt_token_total_supply` before or after the deposit is recorded. 3. In `user_receipt_token_transfer_context.rs`, function `handle_transfer()`, when emitting the `UserTransferredReceiptToken`, it should be clarified if `source_fund_account` and `destination_fund_account` should use placeholders created with the address of the funds, or with the address of the underlying users. 4. In `operator_fund_context.rs`, function `process_fund_withdrawal_job()`, when emitting the event `OperatorProcessedJob`, it should be clarified if `fund_account` should be created with the values of `receipt_token_total_supply` before or after the withdrawal is recorded.

LowIf All Lamports Are Withdrawn From `fund_account`, the Account Data Could Be DeletedAcknowledged

In `user_fund_context.rs`and the function `withdraw()`, if accounting discrepancies occur, no check prevents withdrawing all lamports from `fund_account`, which would result in the deletion of the account's data.

LowImmediate Withdrawals Are PossibleAcknowledged

The protocol implements a withdrawal flow, where a user has to first request a withdrawal, through the `request_withdrawal()`, and then it has to be processed along with other withdrawal requests, if any. To process withdrawal requests, the operator needs to either wait for a pre-determined amount of time between each batch (`batch_processing_threshold_duration`), or a threshold amount (`batch_processing_threshold_amount`). This means that a user with a high stake, that is greater than `batch_processing_threshold_amount` can deposit and withdraw instantly.

LowIt Is Possible to Update `UserRewardPool` without Updating `RewardPool`Acknowledged

In all but one case, the global `RewardPool` is always updated alongside the `UserRewardPool`. During deposits and withdrawals for instance. However, there is one case where a `UserRewardPool` will be updated without updating the `RewardPool` it is part of, namely this is the `update_user_reward_pools()` function that is callable by any user. There are no specific issues that are related to this case, but it might cause issues down the line if some future functionality expects the `UserRewardPool` and `RewardPool` to be updated together.

LowMissing input validationsAcknowledged

**Description** It is important to validate inputs, even if they only come from trusted addresses, to avoid human error: 1. In `update.rs`, it is possible to call `add_holder()` with: a) an empty vector `pubKeys`; b) a vector `pubKeys` containing duplicates; 2. In `fund_manager_fund_supported_token_context.rs`, we can have in `FundManagerFundSupportedTokenContext` the following equality: `receipt_token_mint == supported_token_mint`. 3. In `user_fund_supported_token_context.rs`, function `deposit_supported_token()` and in `user_fund_context.rs`, function `deposit_sol()`, the values of `metadata` (`wallet_provider` and `contribution_accrual_rate`) are not sanitized. 4. In `fund_manager_fund_context.rs`, we can use: a) in `update_sol_withdrawal_fee_rate()` any value for `sol_withdrawal_fee_rate`; b) in `update_batch_processing_threshold()` any value for `amount` and `duration`; 5. It is possible to execute the instruction `fund_manager_settle_reward()` for an `amount` of `0`, which can create a `RewardSettlementBlock` of `amount == 0`.

LowNo Functionality To Withdraw Deposited AssetsAcknowledged

The protocol allows the deposit of a set of supported assets, or simply `SOL`, in exchange for `fragSol`. When users want to withdraw, they will get an amount of `SOL` that is equivalent to the `fragSol` value at the time of withdrawal. However, **there is no functionality for the admin to withdraw the supported tokens deposited by the users**. The protocol will not allow withdrawal at its first stage, which mitigates the risk that users might withdraw all the `SOL` deposited and leave the other supported tokens.

LowRisk of out-of-bounds error in function `init_without_load()`Acknowledged

The functions `init_without_load()` and `bump()` access the value of `data` at a given `offset`. However, no check makes sure that `offset` is not an out-of-bound ID.

LowThe Closure in `check_valid_addition()` Checks Instead if the Addition Is InvalidAcknowledged

The closure `is_contribution_accrual_rate_valid` currently checks if the rate is invalid (i.e., not in the range `100..200`), so the closure name is misleading.

Show 2 more
LowToken Allocation Are not Updated During TransfersAcknowledged

The protocol tracks `fragSol` transfers using a custom transfer hook. Currently, the feature is disabled, and transfers are not allowed. However, the transfer hook does not perform an allocation update for the source and the destination. This means if transfers were to be enabled, specifically in the function `UserReceiptTokenTransferContext.handle_transfer()` the balances and rewards of the source and destination will remain the same.

LowUnderflow Error Can Happen without Explicit Error if a User Executes a Transaction with `user_deposit_sol()` or `user_deposit_supported_token()` as the First Instruction with `metadata`Acknowledged

An underflow error can happen without explicit error if a user executes a transaction with `user_deposit_sol()` or `user_deposit_supported_token()` as the first instruction with `metadata`. In this case, the variable `current_ix_index` in the function `verify_preceding_ed25519_instruction()` will take the value `0`, and underflow will happen at the line: ``` let ix = instructions::load_instruction_at_checked(current_ix_index - 1, instructions_sysvar)?; ```

Contracts in scope

No deployed address is recorded for this audit.

The report names a repository or files. Open the report to see its scope.

Repository and files the report names (1)

  • programs/restaking/src/**

Part of Fragmetric Restaking Program’s security record

Fragmetric Restaking Program
Audits3 audits by 1 firmLast audit Oct 2025, by Quantstamp.
Critical findingsNo open critical findingsAcross 3 reports.
Open Fragmetric Restaking Program’s security record

Security firm

Quantstamp

236 projects reviewed · 332 reports · latest Oct 2026

See Quantstamp’s audits

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