Quantum Audit Logo

Is Solana (Universal) Safe?

On-chain security analysis — is it a scam or legit?

Solana (Universal) USOL
0x9b8d…db55
Base Not verifiedLast checked 3d ago 1 audit on record
How is this score calculated? → Medium Risk
Executive SummaryAI Copilot

The audit of the WrappedAssetV2 contract, serving as the implementation for a BeaconProxy, revealed a robust ERC20 token implementation utilizing OpenZeppelin's upgradeable contracts and access control. Key features include centralized minting/burning and a user blacklist. A critical vulnerability was identified in the custom storage pattern, which poses a significant risk during future upgrades. High centralization of control for token operations and an immutable merchant controller also present notable risks.

1 Critical1 High1 Medium3 Informational
Volume 24h
$649.8K
Liquidity
$1.29M
Price
$104.7500
Token Age
1y
Top 10 Holders
76.6%

Security Findings

Critical

Critical: Custom Storage Pattern Poses Upgrade Risk

C-01The `WrappedAssetV2` contract uses a custom storage pattern where `WrappedAssetV2Storage` is explicitly mapped to a fixed `bytes32` slot (`WrappedAssetV2StorageLocation`) using inline assembly. This approach deviates from standard upgradeable contract storage management (e.g., using OpenZeppelin's `ERC1967Upgrade` or explicit storage gaps). If a future upgrade introduces new state variables or if OpenZeppelin's internal storage layout changes in a way that conflicts with this hardcoded slot, it could lead to storage collisions, data corruption, or loss of funds for users. This is a severe upgrade safety issue (7.1, 7.7).
IssueThe `WrappedAssetV2` contract uses a custom storage pattern where `WrappedAssetV2Storage` is explicitly mapped to a fixed `bytes32` slot (`WrappedAssetV2StorageLocation`) using inline assembly. This approach deviates from standard upgradeable contract storage management (e.g., using OpenZeppelin's `ERC1967Upgrade` or explicit storage gaps). If a future upgrade introduces new state variables or if OpenZeppelin's internal storage layout changes in a way that conflicts with this hardcoded slot, it could lead to storage collisions, data corruption, or loss of funds for users. This is a severe upgrade safety issue (7.1, 7.7).
FixRefactor the storage to use OpenZeppelin's recommended upgradeable storage patterns. This typically involves inheriting from `UUPSUpgradeable` or `TransparentUpgradeableProxy` and defining storage variables directly in the contract, allowing the compiler to manage storage slots. If custom storage is absolutely necessary, ensure it is placed within an explicit storage gap to prevent future collisions.
StatusUnresolved
High

High: Centralized Control Over Token Supply and User Funds

H-01The `mint` and `burn` functions are restricted to the `MERCHANT_CONTROLLER`, granting this single address complete control over the token's supply. Additionally, the `setUserBlacklist` function, restricted to the `RESPONDER_ROLE`, allows blacklisting any user, effectively freezing their funds or preventing them from receiving tokens. This high degree of centralization (7.3, 7.4) introduces significant economic risk, as a compromise or malicious action by these privileged roles could lead to arbitrary minting, burning, or censorship of user funds.
IssueThe `mint` and `burn` functions are restricted to the `MERCHANT_CONTROLLER`, granting this single address complete control over the token's supply. Additionally, the `setUserBlacklist` function, restricted to the `RESPONDER_ROLE`, allows blacklisting any user, effectively freezing their funds or preventing them from receiving tokens. This high degree of centralization (7.3, 7.4) introduces significant economic risk, as a compromise or malicious action by these privileged roles could lead to arbitrary minting, burning, or censorship of user funds.
FixEnsure that the `MERCHANT_CONTROLLER` and `RESPONDER_ROLE` are controlled by robust, multi-signature wallets with high thresholds and strict operational procedures. Clearly document the scope, responsibilities, and limitations of these roles. Consider implementing time locks or additional governance checks for critical actions like large mints or widespread blacklisting.
StatusUnresolved
Medium

Medium: Immutable MERCHANT_CONTROLLER Address

M-01The `MERCHANT_CONTROLLER` address is set as `immutable` in the constructor. This means that if the `MERCHANT_CONTROLLER` address needs to be changed in the future (e.g., due to compromise, operational changes, or an upgrade of the controller itself), it cannot be updated without deploying an entirely new implementation contract and performing an upgrade. This limits operational flexibility and introduces a single point of failure (7.3, 7.8).
IssueThe `MERCHANT_CONTROLLER` address is set as `immutable` in the constructor. This means that if the `MERCHANT_CONTROLLER` address needs to be changed in the future (e.g., due to compromise, operational changes, or an upgrade of the controller itself), it cannot be updated without deploying an entirely new implementation contract and performing an upgrade. This limits operational flexibility and introduces a single point of failure (7.3, 7.8).
FixConsider making the `MERCHANT_CONTROLLER` address configurable via an access-controlled function, allowing it to be updated by the contract's admin role (e.g., the multisig). This would provide greater operational flexibility and resilience without requiring a full contract upgrade for a simple address change.
StatusUnresolved
Info

Informational: Blacklist Logic Clarity

I-01The `_update` function checks `$.userBlacklist[msg.sender] || $.userBlacklist[from] || $.userBlacklist[to]`. While functionally correct, the check for `msg.sender` is often redundant when `msg.sender` is also `from` (as in a direct `transfer`). This does not introduce a vulnerability but could be slightly optimized for clarity or gas if desired (7.2).
IssueThe `_update` function checks `$.userBlacklist[msg.sender] || $.userBlacklist[from] || $.userBlacklist[to]`. While functionally correct, the check for `msg.sender` is often redundant when `msg.sender` is also `from` (as in a direct `transfer`). This does not introduce a vulnerability but could be slightly optimized for clarity or gas if desired (7.2).
FixNo change is strictly required as the logic is correct. For minor optimization, one could consider if `msg.sender` is always `from` in the context of `_update` calls from `transfer` and `transferFrom`, and potentially simplify the condition. However, the current implementation is safe.
StatusUnresolved
Info

Informational: Use of AccessControlDefaultAdminRulesUpgradeable with Delay

I-02The contract correctly utilizes `AccessControlDefaultAdminRulesUpgradeable` with a `ADMIN_TRANSFER_DELAY` of 1 day. This is a good security practice (7.3, 7.5) as it introduces a time delay for critical administrative role changes, providing a window for detection and potential mitigation of malicious or erroneous actions.
IssueThe contract correctly utilizes `AccessControlDefaultAdminRulesUpgradeable` with a `ADMIN_TRANSFER_DELAY` of 1 day. This is a good security practice (7.3, 7.5) as it introduces a time delay for critical administrative role changes, providing a window for detection and potential mitigation of malicious or erroneous actions.
FixMaintain this security feature. Ensure the `ADMIN_TRANSFER_DELAY` is appropriate for the operational security requirements of the protocol.
StatusUnresolved
Info

Informational: Correct Initialization Prevention

I-03The `WrappedAssetV2` constructor correctly calls `_disableInitializers()`. This prevents the implementation contract from being initialized directly, which is a crucial security measure for upgradeable contracts deployed behind a proxy (7.7).
IssueThe `WrappedAssetV2` constructor correctly calls `_disableInitializers()`. This prevents the implementation contract from being initialized directly, which is a crucial security measure for upgradeable contracts deployed behind a proxy (7.7).
FixNo action required. This is a best practice and correctly implemented.
StatusUnresolved

Category Ratings

TechnicalMedium4/10

The contract leverages battle-tested OpenZeppelin libraries for ERC20 and access control, enhancing code security (7.2). The custom blacklist logic within `_update` is correctly implemented to restrict transfers for blacklisted addresses. However, the use of a custom storage slot (`WrappedAssetV2StorageLocation`) for `WrappedAssetV2Storage` deviates from standard upgradeable contract patterns and introduces a high risk of storage collisions in future upgrades (7.1).

GovernanceMedium4/10

The contract implements strong access control (7.3) using `AccessControlDefaultAdminRulesUpgradeable` with a 1-day delay for admin role transfers, which is a good security practice. However, the `mint` and `burn` functions are highly centralized, controlled by an immutable `MERCHANT_CONTROLLER` address, which poses a significant economic risk (7.4) due to its power over token supply. The `RESPONDER_ROLE` also has the power to blacklist any user, effectively freezing their funds (7.5). The immutability of the `MERCHANT_CONTROLLER` limits operational flexibility (7.8).

UpgradesHigh1/10

The contract is designed as an upgradeable implementation for a BeaconProxy, correctly using `Initializable` and calling `_disableInitializers()` in its constructor. This setup generally supports safe upgrades (7.7). However, the custom storage pattern using `WrappedAssetV2StorageLocation` for `WrappedAssetV2Storage` creates a critical risk of storage collisions if future versions or OpenZeppelin library updates introduce conflicting storage variables at that specific slot, potentially leading to data corruption or loss of funds.

Security Checklist

Contract VerifiedPass
Ownership RenouncedFail
No Mint FunctionFail
Liquidity LockedFail
Not a ProxyFail

Proxy Upgrade Controls

Proxy TypeBeacon
ImplementationVerified source
Upgrades (30d)0 · stable

Holder Composition

11.6% in wallets65.0% in contracts
Effective Concentration37.6%

Share held by contracts — treasury, vesting, bridge or staking — is discounted against share held by wallets when the score is computed: a contract cannot decide to sell the way an anonymous holder can, though it can still be drained or voted to sell. Effective concentration is the figure the risk score is actually calculated from.

Liquidity Depth

The risk score reads depth across every pair. The volume figure and the volume-to-liquidity ratio elsewhere on this page describe only the pair this audit analysed, so the two are not directly comparable.

LP Distribution

Top-1 Unlocked Holder35.3%
Top-3 Unlocked65.4%

Key Addresses

Deployer
0x693c…47a2
Unlocked LP Held By
0x7bc6…31e60x7d27…fd550x4701…7cfd0x97e9…f3330x6671…a1390x8809…288c0xaece…1ee10xa2f0…cba70x24d7…ac520xb53d…dc5a

No privileged address appears among these holders: the unlocked liquidity sits with independent providers, not with the deployer.

What Raised This Score

  • Ownership NOT renounced — Multisig (2-of-4)
  • Mintable supply — no cap found, dilution unbounded
  • Proxy contract (upgradeable — admin can replace logic)
  • Complex proxy pattern (BEACON)
  • Top-10 concentration > 30% (76.6% total → 37.6% effective; 11.6% in EOAs, 65.0% in contracts — moderate)
  • Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
  • 1 Critical finding(s) from audit
  • 1 High finding(s) from audit
  • 1 Medium finding(s) from audit

Each factor is an on-chain fact recorded at the time of this analysis. The score is computed from them by a deterministic function, so the same contract returns the same score for anyone who runs the audit. How scores are computed

Related Audits

Nockchain (NOCK)Medium RiskElsaMedium RiskLil Finder Guy (LFG)Medium RiskAerodrome Finance (AERO)Medium RiskaeonHigh RiskSapienMedium Risk

Would You Like a More Detailed Audit of Solana (Universal)?

Our AI-powered scanner gives you a deeper, real-time smart contract analysis — free, with every scoring factor shown.

Get Detailed Audit