Introduction
We express our gratitude to the PrigeeX team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.
PrigeeX is a decentralized exchange protocol deployed on Arbitrum, built as a rebrand and extension of Uniswap V2 and V3. The protocol introduces a custom layer consisting of a native PGX governance token, a staking mechanism for PGX holders, and an automated fee distribution system that collects protocol fees from V3 liquidity pools, swaps them into PGX, and splits the proceeds between stakers (70%) and a treasury multisig (30%).
Document | |
|---|---|
| Name | Smart Contract Code Review and Security Analysis Report for PrigeeX |
| Audited By | Olesia Bilenka |
| Approved By | Kerem Solmaz |
| Website | https://www.prigeex.com/→ |
| Changelog | 21/07/2026 - Preliminary Report |
| 11/08/2026 - Final Report | |
| Platform | Arbitrum One |
| Language | Solidity |
| Tags | Fungible Token; Permit Token; Staking; Oracle; Upgradable |
| Methodology | https://docs.hacken.io/methodologies/smart-contracts→ |
Document
- Name
- Smart Contract Code Review and Security Analysis Report for PrigeeX
- Audited By
- Olesia Bilenka
- Approved By
- Kerem Solmaz
- Website
- https://www.prigeex.com/→
- Changelog
- 21/07/2026 - Preliminary Report
- 11/08/2026 - Final Report
- Platform
- Arbitrum One
- Language
- Solidity
- Tags
- Fungible Token; Permit Token; Staking; Oracle; Upgradable
Review Scope | |
|---|---|
| Repository | https://github.com/PrigeeX/PrigeeX_contracts→ |
| Commit | 8612552 |
| Remediation commit | 41ccad7 |
Review Scope
- Commit
- 8612552
- Remediation commit
- 41ccad7
Audit Summary
The system users should acknowledge all the risks summed up in the risks section of the report
Documentation quality
Functional requirements are well documented in
STAKING_AND_FEE_DISTRIBUTION.mdwith SRS traceability (SC-01 through SC-35).Technical description is comprehensive, covering:
Architecture overview with end-to-end fee flow diagrams
Industry-standard compliance mapping (Synthetix, Uniswap, OpenZeppelin)
Deliberate deviations with "not harmful" rationale
Deployment order and operational runbooks
Admin powers and trust assumptions matrix
OpenZeppelin library version layout (v3.4.2, v4.9.6)
NatSpec documentation is present in all in-scope contracts.
Deployment guides (
DEPLOY_ARB_SEPOLIA.md,deployments/arb-one.md,deployments/arb-sepolia.md) and operational runbooks are provided.
Code quality
The code properly reuses OpenZeppelin contracts (
Ownable2Step,ReentrancyGuard,Pausable,UUPSUpgradeable, ERC20 extensions).Industry-standard patterns are applied:
Synthetix-style reward-per-token for staking (1e27 RAY precision)
UUPS proxy for upgradeability with 49-slot
__gapOwnable2Stepfor secure two-phase ownership transfersTWAP-bounded permissionless swaps for MEV protection
The development environment is well configured with multi-version Solidity support (0.5.16, 0.6.6, 0.7.6, 0.8.x), proper remappings, and optimizer settings (
optimizer_runs = 200,bytecode_hash = "none"for deterministic CREATE2).Modifier-based access control and event emissions follow best practices.
Code structure separates concerns clearly (token, staking, fee distribution, oracle wrapper).
Test coverage
Branch coverage could not be measured due to multi-version Solidity architecture conflicts (legacy V2/V3 fork contracts cause "stack too deep" errors when compiled without optimizer for coverage instrumentation).
Positive cases (happy paths) are covered: staking, unstaking, reward distribution, fee collection, TWAP queries, 70/30 split.
Negative cases are covered: reverts on zero amounts, insufficient balances, unauthorized access, paused state, zero stakers, expired deadlines, non-allowlisted tokens.
Multi-user interactions are tested (alice, bob, charlie scenarios, proportional reward splits).
Fuzz tests are included:
testFuzz_stakeUnstake_principalExact— principal integritytestFuzz_rewards_proportional— reward distribution correctnesstestFuzz_transfer/testFuzz_constructorSupply— token invariants
Edge cases are covered:
Pause behavior (stake blocked, unstake/claim allowed)
Emergency withdraw limits (
totalStaked + rewardReserveprotection)TWAP slippage enforcement with floor and ceiling bounds
Two-step ownership transfer
Fee token allowlist (F-2026-18085)
Caller-supplied deadline (F-2026-18086)
TWAP window bounds (F-2026-18091)
Max slippage limit (F-2026-18081)
PGX recovery prevention (F-2026-18083)
Integration test (
Integration.t.sol) validates end-to-end: real V3 pool creation, oracle observation building, stake → distribute → 70/30 split verification with TWAP enforcement.V2/V3 Fork test coverage (per
TEST_PROGRESS.md): 743 tests passing across 44/48 upstream specs translated to Foundry.
System Overview
The in-scope contracts form the protocol's revenue distribution and tokenomics subsystem, operating independently atop the forked V2/V3 AMM core. At the center is PrigeeXFeeDistributor, which is designated as the V3 factory owner—a requirement for calling collectProtocol on pools, as Uniswap V3's fee collection is gated on factory ownership. When triggered, the distributor collects accumulated protocol fees from specified V3 pools, swaps non-PGX tokens into PGX via the configured swap router, and routes the resulting balance according to the staking share configuration.
PrigeeXToken.sol — The PGX ERC-20 governance and utility token. Implements fixed, capped supply with all tokens minted to the treasury at deployment; supports gasless approvals via EIP-2612 Permit, optional burning via ERC20Burnable, and vote delegation via ERC20Votes.
PrigeeXStaking.sol — UUPS-upgradeable staking contract allowing users to stake PGX and earn proportional protocol fee revenue. Implements Synthetix-style reward-per-token accounting at 1e27 precision, permissionless depositRewards for the fee distributor, and owner-restricted emergency withdrawal limited to surplus tokens above staked principal and unclaimed rewards.
PrigeeXFeeDistributor.sol — Non-upgradeable fee collection and distribution contract. Collects protocol fees from V3 pools via collectProtocol, swaps fee tokens to PGX using a configurable router with TWAP-enforced slippage protection, and splits proceeds between staking rewards and treasury. Exposes factory-owner passthroughs via transferFactoryOwnership, enableFeeAmount, and setPoolFeeProtocol.
PrigeeXTwapOracle.sol — Stateless Solidity 0.7.6 view contract wrapping Uniswap V3's OracleLibrary. Exposes consultQuote to return the TWAP-derived expected output for a given input amount, enabling the fee distributor to enforce MEV-resistant minimum swap outputs from 0.8.x code.
Privileged roles
PrigeeXTokensol
No privileged roles. The entire capped supply is minted to the treasury address at deployment; no mint function exists, and the contract inherits no access control.
PrigeeXStakingsol
owner (inherited from OwnableUpgradeable): Administrative control over the staking contract.
Can call
_authorizeUpgradeto authorize UUPS proxy upgrades to a new implementation.Can call
emergencyWithdrawto recover surplus tokens (limited to amounts exceedingtotalStaked + rewardReservefor the staking token; other tokens may be fully recovered).Can call
pauseto halt new stake deposits (unstaking and reward claims remain enabled).Can call
unpauseto resume stake deposits.Can call
transferOwnershipto transfer ownership to a new address.Can call
renounceOwnershipto permanently remove the owner role.
PrigeeXFeeDistributorsol
owner (inherited from Ownable2Step): Full administrative control over fee distribution parameters and V3 factory operations.
Can call
transferFactoryOwnershipto transfer V3 factory ownership to a new address.Can call
enableFeeAmountto enable a new fee tier on the V3 factory.Can call
setPoolFeeProtocolto set the protocol fee fraction on a specific V3 pool.Can call
setTreasuryto update the treasury address receiving the non-staking share of fees.Can call
setStakingShareto update the staking share percentage (0–100% in basis points).Can call
setSwapRouterto update the swap router address used for fee-to-PGX conversions.Can call
setTwapWindowto update the TWAP averaging window (minimum 60 seconds).Can call
setMaxSlippageto update the maximum allowed slippage versus TWAP (in basis points).Can call
setTwapOracleto update the TWAP oracle contract address.Can call
recoverTokento recover any ERC-20 token balance held by the contract.Can call
transferOwnershipto initiate two-step ownership transfer.Cannot call
renounceOwnership— the function is disabled and reverts unconditionally.
pendingOwner (inherited from Ownable2Step): The address nominated to become the new owner.
Can call
acceptOwnershipto finalize ownership transfer initiated by the current owner.
PrigeeXTwapOraclesol
No privileged roles. The contract is a stateless view-only wrapper around
OracleLibrarywith no administrative functions.
Potential Risks
Limited Audit Coverage: The in-scope boundary covers only 5 of the 92 Solidity files in the repository. The PrigeeXFeeDistributor, PrigeeXStaking, PrigeeXToken, ERC1967Proxy, and PrigeeXTwapOracle contracts have been reviewed, while the underlying V3 core (factory, pools), V3 periphery (SwapRouter, OracleLibrary), and all other protocol infrastructure remain out of scope. Security guarantees extend only to the logic within the reviewed contracts and do not cover vulnerabilities that may exist in the broader protocol infrastructure they depend upon.
V3 Factory and Pool Interactions: The PrigeeXFeeDistributor contract interacts extensively with out-of-scope V3 infrastructure through calls to factory.getPool, factory.setOwner, factory.enableFeeAmount, pool.collectProtocol, and pool.setFeeProtocol. These calls assume the V3 core contracts behave as the unmodified Uniswap-v3 implementation. Any deviations or vulnerabilities in the out-of-scope V3 contracts could affect fee collection, protocol fee configuration, and factory ownership transfers.
Swap Router Dependency: The distribute function in PrigeeXFeeDistributor relies on the out-of-scope SwapRouter via ISwapRouter.exactInputSingle to convert collected fee tokens into PGX. The contract assumes the router will correctly execute swaps and return accurate output amounts. If the configured router behaves unexpectedly or is compromised, fee swaps could fail or produce incorrect results.
Oracle Library Dependency: The PrigeeXTwapOracle contract wraps out-of-scope Uniswap-v3 OracleLibrary.consult and OracleLibrary.getQuoteAtTick functions compiled under Solidity 0.7.6. The TWAP price floor mechanism in PrigeeXFeeDistributor is entirely dependent on the correctness of these library functions. Any bugs in the OracleLibrary could produce incorrect TWAP quotes, leading to inadequate slippage protection.
Fee Distributor Owner Powers: The owner of PrigeeXFeeDistributor holds significant administrative authority including: setting the treasury recipient via setTreasury, adjusting the staking/treasury split from 0% to 100% via setStakingShare, replacing the swap router via setSwapRouter, modifying TWAP parameters via setTwapWindow and setMaxSlippage, curating the fee token allowlist via setFeeTokenAllowed, and exercising full V3 factory owner powers via transferFactoryOwnership, enableFeeAmount, and setPoolFeeProtocol. A compromised or malicious owner could redirect all protocol fees to an arbitrary treasury address, disable staking rewards entirely, or transfer factory ownership to an attacker-controlled address.
Staking Contract Owner Powers: The owner of PrigeeXStaking can upgrade the contract implementation via UUPS and pause staking operations via pause. While unstake and claimRewards bypass the pause, a malicious upgrade could alter withdrawal logic to trap user funds or steal staked principal.
No Timelock or Multi-Signature Enforcement: Neither PrigeeXFeeDistributor nor PrigeeXStaking enforce on-chain timelocks or multi-signature requirements for sensitive administrative operations. The contracts rely on the owner address being a properly configured multisig at deployment, but this assumption is not enforced at the smart contract level. If ownership is transferred to an EOA or compromised multisig, all owner-gated functions become single-point-of-failure attack vectors.
UUPS Upgrade Without Constraints: The PrigeeXStaking contract implements UUPS upgradeability with _authorizeUpgrade gated solely by onlyOwner. There is no on-chain timelock, no upgrade delay, and no upgrade cancellation mechanism. The owner can atomically deploy a new implementation and upgrade in a single transaction, leaving no window for users to exit before potentially malicious code takes effect.
Storage Layout Sensitivity: The PrigeeXStaking contract stores critical user state in the stakedBalance mapping and global accounting variables (totalStaked, rewardPerTokenStored, totalRewardsDeposited, rewardReserve). Future upgrades must preserve the exact storage layout to avoid corrupting user balances and reward calculations. The 49-slot __gap provides buffer space, but an implementation error in a future upgrade could still cause storage collision and irreversible state corruption.
Immutable Proxy Initialization: The ERC1967Proxy contract is a minimal implementation that stores the implementation address once in the constructor and provides no administrative functions. The proxy itself cannot be upgraded or have its implementation changed except through the UUPS mechanism in the implementation contract. If the implementation's upgrade mechanism is ever disabled or bricked, the proxy becomes permanently locked to its current implementation.
TWAP Observation Cardinality Requirement: The TWAP-based slippage floor in PrigeeXFeeDistributor requires that each tokenIn/PGX pool has sufficient observation history spanning the configured twapWindow (default 1800 seconds). If increaseObservationCardinalityNext has not been called on a pool, twapOracle.consultQuote will revert and the swap will be skipped via SwapSkipped. Newly allowlisted tokens may be unswappable until their pool's oracle buffer is properly initialized.
Oracle Manipulation in Thin Pools: The TWAP floor is read from the same pool that executes the swap. In pools with low liquidity, an attacker could potentially move the TWAP over multiple blocks at relatively low cost, then sandwich the distribute call while the floor is artificially suppressed. The contract mitigates this through the owner-curated allowedFeeToken mapping, but the security assumption relies on the owner only allowlisting tokens with sufficiently deep pools.
Stale TWAP in Volatile Markets: The configurable twapWindow is bounded between 15 minutes (MIN_TWAP_WINDOW) and 24 hours (MAX_TWAP_WINDOW). During periods of high volatility, a 30-minute default TWAP may significantly lag spot prices, causing the TWAP floor to permit worse-than-expected execution or, conversely, causing swaps to revert unnecessarily when spot price has moved favorably beyond the slippage tolerance.
Permissionless But Caller-Dependent Distribution: The distribute function in PrigeeXFeeDistributor is permissionless but requires the caller to supply correct pools and swaps parameters. No on-chain registry enumerates which pools have accumulated fees or which fee tokens should be swapped. If off-chain infrastructure fails to call distribute with appropriate parameters, protocol fees accumulate in V3 pools and the FeeDistributor contract without reaching stakers or the treasury.
Deadline Parameter Relies on Off-Chain Coordination: The distribute function accepts a deadline parameter that must be set off-chain to provide transaction expiry protection. The contract explicitly notes that deriving deadline from block.timestamp on-chain would always pass. If callers set excessively long deadlines or fail to set them appropriately, stale transactions could execute at unfavorable prices long after submission.
Staking State Check at Distribution Time: The PrigeeXFeeDistributor contract checks stakingContract.totalStaked at distribution time. If no tokens are staked, the staking share is redirected to the treasury to prevent the depositRewards call from reverting. This creates a race condition where the last unstaker could cause pending distribute transactions to route all rewards to treasury instead of waiting for new stakers.
Pause State Asymmetry: The pause function in PrigeeXStaking blocks new stake calls but explicitly allows unstake and claimRewards to proceed. During a pause, stakers can exit and claim but no new stake can enter. If PrigeeXFeeDistributor calls depositRewards during this window, rewards are distributed to a potentially diminishing staker pool, concentrating rewards among remaining stakers who may exit immediately after claiming.
Findings
Code ― | Title | Status | Severity | |
|---|---|---|---|---|
| F-2026-1808 | Absence of Minimum Stake Duration Enables Flash Loan Attack on Reward Distribution | fixed | High | |
| F-2026-1808 | TWAP-Based Slippage Protection Can Be Circumvented in Low-Liquidity Pools | fixed | Medium | |
| F-2026-1809 | Minimum TWAP Window of 60 Seconds in setTwapWindow Is Insufficient for Manipulation Resistance | fixed | Low | |
| F-2026-1808 | Swap Deadline Set to block.timestamp in distribute Provides No Transaction Expiry Protection | fixed | Low | |
| F-2026-1808 | Unrestricted recoverToken Allows Owner to Sweep Undistributed PGX | fixed | Low | |
| F-2026-1808 | Missing Upper Bound on setMaxSlippage Allows Complete Disabling of Slippage Protection | fixed | Low | |
| F-2026-1809 | Floating Pragma Allows Compilation With Untested Compiler Versions | mitigated | Observation | |
| F-2026-1809 | Missing Event Emissions in enableFeeAmount and setPoolFeeProtocol Hinders Off-Chain Monitoring | fixed | Observation | |
| F-2026-1808 | Interface Documentation Incorrectly States Reward Precision as 1e18 | fixed | Observation | |
| F-2026-1808 | Rounding Truncation in depositRewards Results in Dust Loss Over Time | accepted | Observation |
Appendix 1. Definitions
Severities
When auditing smart contracts, Hacken is using a risk-based approach that considers Likelihood, Impact, Exploitability and Complexity metrics to evaluate findings and score severities.
Reference on how risk scoring is done is available through the repository in our Github organization:
Severity | Description |
|---|---|
Critical | Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation. |
High | High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation. |
Medium | Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category. |
Low | Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution. |
Severity
- Critical
Description
- Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation.
Severity
- High
Description
- High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation.
Severity
- Medium
Description
- Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category.
Severity
- Low
Description
- Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution.
Potential Risks
The "Potential Risks" section identifies issues that are not direct security vulnerabilities but could still affect the project’s performance, reliability, or user trust. These risks arise from design choices, architectural decisions, or operational practices that, while not immediately exploitable, may lead to problems under certain conditions. Additionally, potential risks can impact the quality of the audit itself, as they may involve external factors or components beyond the scope of the audit, leading to incomplete assessments or oversight of key areas. This section aims to provide a broader perspective on factors that could affect the project's long-term security, functionality, and the comprehensiveness of the audit findings.
Appendix 2. Scope
The scope of the project includes the following smart contracts from the provided repository:
Scope Details | |
|---|---|
| Repository | https://github.com/PrigeeX/PrigeeX_contracts→ |
| Commit | 8612552402ce33927b783078590b11716c5ea5c5 |
| Remediation commit | 41ccad72ead1f66e11258e9f6b8b4d9a71e9c460 |
| Requirements | https://github.com/PrigeeX/PrigeeX_contracts/blob/main/README.md;→ |
Scope Details
- Commit
- 8612552402ce33927b783078590b11716c5ea5c5
- Remediation commit
- 41ccad72ead1f66e11258e9f6b8b4d9a71e9c460
Assets in Scope
Appendix 3. Additional Valuables
Additional Recommendations
The smart contracts in the scope of this audit could benefit from the introduction of automatic emergency actions for critical activities, such as unauthorized operations like ownership changes or proxy upgrades, as well as unexpected fund manipulations, including large withdrawals or minting events. Adding such mechanisms would enable the protocol to react automatically to unusual activity, ensuring that the contract remains secure and functions as intended.
To improve functionality, these emergency actions could be designed to trigger under specific conditions, such as:
Detecting changes to ownership or critical permissions.
Monitoring large or unexpected transactions and minting events.
Pausing operations when irregularities are identified.
These enhancements would provide an added layer of security, making the contract more robust and better equipped to handle unexpected situations while maintaining smooth operations.
Frameworks and Methodologies
This security assessment was conducted in alignment with recognised penetration testing standards, methodologies and guidelines, including the NIST SP 800-115 – Technical Guide to Information Security Testing and Assessment →, and the Penetration Testing Execution Standard (PTES) →, These assets provide a structured foundation for planning, executing, and documenting technical evaluations such as vulnerability assessments, exploitation activities, and security code reviews. Hacken’s internal penetration testing methodology extends these principles to Web2 and Web3 environments to ensure consistency, repeatability, and verifiable outcomes.