Quantum Audit Logo

Is Coinbase Wrapped ADA Safe?

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

Coinbase Wrapped ADA CBADA
0xcbad…7b8c
Base
Not verifiedThis record has not gone through deep verification and is not being monitored. The score is a dated snapshot — the token’s risk can change at any time.
Last checked 3d ago 1 audit on record
Executive SummaryAI Copilot

This audit covers the FiatTokenV2_2 contract, which serves as the implementation logic for an upgradeable ERC-20 token. The contract incorporates advanced features such as EIP-712 authorizations, blacklisting, and a custom bit-packed storage solution for balances and blacklist states. While the contract demonstrates careful implementation, the custom storage pattern introduces significant complexity and potential upgradeability challenges. Several findings highlight areas for review, particularly concerning storage layout, EIP-712 versioning, and non-standard initialization behaviors.

1 High2 Medium1 Low1 Informational
Volume 24h
$691.3K
Liquidity
$105.7K
Price
$0.2233
Token Age
1y
Top 10 Holders
94.0%

Security Findings

High

Complex Custom Storage for Balances and Blacklisting

H-01The `balanceAndBlacklistStates` mapping uses a custom bit-packing strategy to store both the account balance (lower 255 bits) and the blacklist status (highest bit, 2^255) within a single `uint256`. While the `_setBalance`, `_balanceOf`, `_isBlacklisted`, and `_setBlacklistState` functions are designed to manage this, this non-standard storage pattern significantly increases complexity (7.1 Architecture, 7.2 Code Security). Any subtle error in bitwise operations or a misunderstanding of this pattern by future developers could lead to incorrect balances, incorrect blacklist states, or critical storage collisions during upgrades, potentially corrupting token data.
IssueThe `balanceAndBlacklistStates` mapping uses a custom bit-packing strategy to store both the account balance (lower 255 bits) and the blacklist status (highest bit, 2^255) within a single `uint256`. While the `_setBalance`, `_balanceOf`, `_isBlacklisted`, and `_setBlacklistState` functions are designed to manage this, this non-standard storage pattern significantly increases complexity (7.1 Architecture, 7.2 Code Security). Any subtle error in bitwise operations or a misunderstanding of this pattern by future developers could lead to incorrect balances, incorrect blacklist states, or critical storage collisions during upgrades, potentially corrupting token data.
FixThoroughly document the custom storage pattern, including its design rationale, invariants, and potential pitfalls. Consider formal verification for the bitwise operations to ensure their correctness under all conditions. For future versions, evaluate if a more standard storage approach (e.g., separate mappings for balances and blacklist status) could be adopted, even if it incurs higher gas costs, to reduce complexity and improve maintainability and upgrade safety.
StatusUnresolved
Medium

Hardcoded EIP-712 Domain Separator Version

M-01The `_domainSeparator()` function hardcodes the EIP-712 domain separator version as the string literal `"2"`. This value is used in the EIP-712 signature generation for functions like `permit` and `transferWithAuthorization` (7.2 Code Security). If a future protocol upgrade or a change in EIP-712 standards requires modifying this version identifier (e.g., to `"3"`), it would necessitate deploying an entirely new implementation contract. This limits the flexibility of future upgrades related to EIP-712 functionality.
IssueThe `_domainSeparator()` function hardcodes the EIP-712 domain separator version as the string literal `"2"`. This value is used in the EIP-712 signature generation for functions like `permit` and `transferWithAuthorization` (7.2 Code Security). If a future protocol upgrade or a change in EIP-712 standards requires modifying this version identifier (e.g., to `"3"`), it would necessitate deploying an entirely new implementation contract. This limits the flexibility of future upgrades related to EIP-712 functionality.
FixConsider making the EIP-712 domain separator version configurable by an authorized role (e.g., owner or admin) through a setter function, or store it in a state variable that can be updated during an upgrade. This would allow for greater flexibility in adapting to future EIP-712 standard changes or protocol versioning without requiring a full contract redeployment.
StatusUnresolved
Medium

Unusual Self-Blacklisting in Initialization

M-02The `initializeV2_2` function explicitly blacklists `address(this)` (the contract itself) using `_blacklist(address(this))` (7.3 Access Control, 7.8 Operations). While this might be an intentional design choice to prevent the token contract from holding its own tokens, it is an unusual pattern. If the contract's functionality were to evolve to require holding tokens (e.g., for staking, liquidity provision, or integration with other protocols), this self-blacklisting would prevent such operations and could lead to unexpected behavior or stuck funds if tokens are inadvertently sent to the contract.
IssueThe `initializeV2_2` function explicitly blacklists `address(this)` (the contract itself) using `_blacklist(address(this))` (7.3 Access Control, 7.8 Operations). While this might be an intentional design choice to prevent the token contract from holding its own tokens, it is an unusual pattern. If the contract's functionality were to evolve to require holding tokens (e.g., for staking, liquidity provision, or integration with other protocols), this self-blacklisting would prevent such operations and could lead to unexpected behavior or stuck funds if tokens are inadvertently sent to the contract.
FixClearly document the rationale behind blacklisting `address(this)` and its intended implications. Ensure that all current and future integrations and operational procedures are aware of this behavior and account for it. If there's any possibility the contract might need to hold tokens in the future, consider removing this self-blacklisting or implementing a mechanism for an authorized role to unblacklist the contract.
StatusUnresolved
Low

Potential for User Front-running in EIP-712 Functions

L-01Functions like `permit`, `transferWithAuthorization`, and `receiveWithAuthorization` rely on EIP-712 signed messages. While this enables gasless transactions, users are susceptible to front-running attacks (7.4 Economic, 7.6 External). A malicious actor could observe a pending signed transaction, reconstruct it, and submit their own transaction with a higher gas price to execute it first, potentially exploiting the user's signed intent. This is a common risk for off-chain signed transactions.
IssueFunctions like `permit`, `transferWithAuthorization`, and `receiveWithAuthorization` rely on EIP-712 signed messages. While this enables gasless transactions, users are susceptible to front-running attacks (7.4 Economic, 7.6 External). A malicious actor could observe a pending signed transaction, reconstruct it, and submit their own transaction with a higher gas price to execute it first, potentially exploiting the user's signed intent. This is a common risk for off-chain signed transactions.
FixAdvise users to always set a sufficiently short `deadline` for EIP-712 signed messages to minimize the window for front-running. Provide clear warnings and best practices in user-facing documentation regarding the risks associated with signed transactions and the importance of transaction deadlines.
StatusUnresolved
Info

Use of Assembly for `_chainId()`

I-01The `_chainId()` function retrieves the chain ID using inline assembly (`assembly { chainId := chainid() }`) (7.2 Code Security). While this is a valid and common pattern in Solidity versions prior to 0.8.0, the `block.chainid` global variable provides a more readable and idiomatic way to access the chain ID in newer Solidity versions. Using assembly can sometimes introduce subtle bugs if not handled carefully.
IssueThe `_chainId()` function retrieves the chain ID using inline assembly (`assembly { chainId := chainid() }`) (7.2 Code Security). While this is a valid and common pattern in Solidity versions prior to 0.8.0, the `block.chainid` global variable provides a more readable and idiomatic way to access the chain ID in newer Solidity versions. Using assembly can sometimes introduce subtle bugs if not handled carefully.
FixFor future upgrades to Solidity 0.8.0 or higher, consider replacing the inline assembly with `block.chainid` for improved readability and maintainability. For the current version, ensure the assembly code is thoroughly tested and understood.
StatusUnresolved

Category Ratings

TechnicalMedium6/10

The contract utilizes SafeMath for arithmetic operations, mitigating common integer overflow/underflow vulnerabilities (7.2 Code Security). It also implements EIP-712 for gasless approvals and transfers, enhancing user experience. However, a significant architectural decision involves a custom bit-packed storage pattern for `balanceAndBlacklistStates`, combining balance and blacklist status in a single `uint256` (7.1 Architecture). While carefully implemented, this non-standard approach increases code complexity and the risk of subtle bugs, especially during future upgrades. Access control (7.3 Access Control) relies on inherited roles for pausing and blacklisting, which is standard for centralized stablecoins.

GovernanceHigh1/10

As a centralized stablecoin, the economic model inherently relies on an issuer with capabilities such as minting, burning, pausing, and blacklisting (7.4 Economic). The contract includes blacklisting functionality, which is a core feature for regulatory compliance in such assets. The `initializeV2_2` function performs a migration of blacklisted accounts, demonstrating active operational management (7.8 Operations). While these centralized controls present inherent governance risks (7.5 Governance), they are expected for this type of token and are generally well-defined within the contract's design.

UpgradesHigh1/10

The contract is designed to be upgradeable via a proxy pattern, with `FiatTokenV2_2` serving as an implementation contract. The `initializeV2_2` function manages the upgrade logic, including symbol updates and migration of blacklisted accounts (7.7 Upgrades). A significant concern for future upgrades is the custom bit-packed storage layout for `balanceAndBlacklistStates`. Any change to this storage pattern in subsequent versions could lead to critical storage collisions or data corruption if not handled with extreme precision. Additionally, the EIP-712 domain separator version is hardcoded, limiting flexibility for future EIP-712 standard updates without a new implementation.

Security Checklist

Contract VerifiedPass
Ownership RenouncedFail
No Mint FunctionFail
Liquidity LockedFail
Not a ProxyFail
HoneypotNoneBuy Tax0.0%Sell Tax0.0%

Proxy Upgrade Controls

Proxy TypeZeppelin Os Legacy
AdminEOA (single key controls upgrades)
ImplementationVerified source
Upgrades (30d)0 · stable

Holder Composition

9.5% in wallets84.6% in contracts
Effective Concentration43.3%

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 Holder98.2%
Top-3 Unlocked100.0%

Key Addresses

Deployer
0x480e…3332
Unlocked LP Held By
0x73e5…91ad0x6be0…37bb

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 — owner is an EOA (single private key)
  • Mintable supply — no cap found, dilution unbounded
  • Proxy contract (upgradeable — admin can replace logic)
  • Admin is EOA (single key controls upgrades)
  • Top-10 concentration > 30% (94.0% total → 43.3% effective; 9.5% in EOAs, 84.6% in contracts — moderate)
  • Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
  • LP top1 unlocked holder = 98.2% (independent LP — depth risk, pool = 56% of DEX liquidity)
  • LP top3 unlocked holders = 100.0% (independent LP — depth risk, pool = 56% of DEX liquidity)
  • 1 High finding(s) from audit
  • 2 Medium finding(s) from audit
  • 1 Low 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

ResearchCoin (RSC)High RiskFren PetHigh RiskVoice of the Gods by Virtuals (ADM)High Riskether.fi governance token (ETHFI)High RiskCluster Protocol (CP)High RiskMetronome Synth USD (MSUSD)High Risk

Would You Like a More Detailed Audit of Coinbase Wrapped ADA?

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

Get Detailed Audit