This audit covers the FiatTokenV2_2 contract, which serves as the implementation logic for a USDC stablecoin proxy on the Base network. The contract implements ERC-20 functionalities, EIP-712 signed messages, and a custom blacklisting mechanism. The codebase is generally well-structured and follows established patterns for stablecoin operations, including upgradeability. Key findings highlight the inherent centralization risks typical for stablecoins and the complexity introduced by a non-standard blacklist storage method.
On-chain security analysis — is it a scam or legit?
Is EURC Safe?
Not verified
This 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.Own this token? Put it under verification →This audit covers the FiatTokenV2_2 contract, which serves as the implementation logic for a USDC stablecoin proxy on the Base network.
Read the full analysis- Ownership not renounced — owner is an EOA
- Mintable supply — no cap found, dilution unbounded
- Proxy contract
- Admin is EOA
- Top-10 concentration > 30%
- Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
- 1 High finding(s) from audit
- 1 Medium finding(s) from audit
- 2 Low finding(s) from audit
Exact factors
- 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% (47.8% total → 37.9% effective; 31.3% in EOAs, 16.5% in contracts — moderate)
- Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
- 1 High finding(s) from audit
- 1 Medium finding(s) from audit
- 2 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
Security Checklist
as of audit · Sep 4Holders
as of audit · Sep 4, 2026- Contractstreasury, vesting, bridge, staking16.5%
- Walletsanonymous holders, free to sell31.3%
- Everyone elsethe rest of the supply52.2%
How holder types affect the score
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.
Holder balances as recorded by the audit of Sep 4, 2026
Liquidity
as of audit · Sep 4- AerodromeUSDCAnalysed$2.14M49.6%
- AerodromeWETH$758.0K17.6%
- AerodromeUSDC$426.9K9.9%
- AerodromecbBTC$251.3K5.8%
- PancakeswapUSDC$156.6K3.6%
- Uniswap v4USDC$114.5K2.7%
Show 4 more pairs
The 20 remaining pairs hold $151.0K between them and are not listed. The risk score reads depth across every pair.
The LP tokens of the analysed pool are not locked or burned, so whoever holds them can withdraw that liquidity.
0x35f9…82cf0xa94f…6b2a0xd392…74700x7d27…fd550x6520…fd220xde40…d2580x8e0d…7b280x64d8…f6980x6fa3…1a490x1eec…2bcdNo privileged address appears among these holders: the unlocked liquidity sits with independent providers, not with the deployer.
Security Findings
HighCentralized Control and Single Point of Failure
The contract design, typical for a centralized stablecoin, grants significant power to a small set of privileged addresses (admin, owner, pauser, blacklister). These roles can pause transfers, blacklist accounts, and control contract upgrades. The proxy's admin is an EOA, representing a single point of failure for upgradeability and overall contract control. A compromise of this EOA could lead to unauthorized upgrades or manipulation of critical contract functions (7.3 Access Control, 7.5 Governance, 7.8 Operations).H-01
Issue
The contract design, typical for a centralized stablecoin, grants significant power to a small set of privileged addresses (admin, owner, pauser, blacklister). These roles can pause transfers, blacklist accounts, and control contract upgrades. The proxy's admin is an EOA, representing a single point of failure for upgradeability and overall contract control. A compromise of this EOA could lead to unauthorized upgrades or manipulation of critical contract functions (7.3 Access Control, 7.5 Governance, 7.8 Operations).
Fix
While inherent to stablecoin design, consider implementing multi-signature wallets or a time-locked governance mechanism for critical administrative functions, especially the proxy admin, to reduce the risk associated with a single EOA compromise. This enhances operational security and resilience against key loss.
Status
Unresolved
MediumNon-Standard Balance and Blacklist Storage Mechanism
The contract employs a custom storage mechanism where balanceAndBlacklistStates uses a single uint256 to store both an account's balance (lower 255 bits) and its blacklist status (most significant bit). While the implementation appears correct and includes checks like _balance <= ((1 << 255) - 1) to prevent overflow into the blacklist bit, this non-standard approach increases complexity and could be a source of subtle bugs or integration issues if not perfectly maintained or understood by external systems (7.1 Architecture, 7.2 Code Security).M-01
Issue
The contract employs a custom storage mechanism where balanceAndBlacklistStates uses a single uint256 to store both an account's balance (lower 255 bits) and its blacklist status (most significant bit). While the implementation appears correct and includes checks like _balance <= ((1 << 255) - 1) to prevent overflow into the blacklist bit, this non-standard approach increases complexity and could be a source of subtle bugs or integration issues if not perfectly maintained or understood by external systems (7.1 Architecture, 7.2 Code Security).
Fix
Ensure thorough internal documentation and testing for this custom storage logic. Future upgrades or integrations should exercise extreme caution when interacting with or modifying this specific storage pattern to prevent unintended side effects or data corruption.
Status
Unresolved
LowSelf-Blacklisting in initializeV2_2
The initializeV2_2 function explicitly blacklists the contract's own address (_blacklist(address(this))). While this might be intended to prevent tokens from being accidentally sent to and locked within the contract itself, it is an unusual pattern that could have unforeseen implications for future interactions or integrations if not fully understood by all parties (7.2 Code Security, 7.8 Operations).L-01
initializeV2_2Issue
The initializeV2_2 function explicitly blacklists the contract's own address (_blacklist(address(this))). While this might be intended to prevent tokens from being accidentally sent to and locked within the contract itself, it is an unusual pattern that could have unforeseen implications for future interactions or integrations if not fully understood by all parties (7.2 Code Security, 7.8 Operations).
Fix
Document the precise rationale behind blacklisting the contract address. Confirm that this action does not interfere with any expected contract functionalities, such as receiving tokens from other contracts, or future upgrade paths that might require the contract to hold tokens temporarily.
Status
Unresolved
LowReliance on _chainId() for EIP-712 Domain Separator
The _domainSeparator() function uses _chainId() (which retrieves the chain ID via assembly) as part of the EIP-712 domain separator. While standard practice for EIP-712, if the contract were to be deployed on a chain with an unexpected chain ID, or if a chain's ID were to change (highly improbable for established networks), it would invalidate all existing EIP-712 signatures, requiring users to re-sign (7.2 Code Security, 7.6 External).L-02
_chainId() for EIP-712 Domain SeparatorIssue
The _domainSeparator() function uses _chainId() (which retrieves the chain ID via assembly) as part of the EIP-712 domain separator. While standard practice for EIP-712, if the contract were to be deployed on a chain with an unexpected chain ID, or if a chain's ID were to change (highly improbable for established networks), it would invalidate all existing EIP-712 signatures, requiring users to re-sign (7.2 Code Security, 7.6 External).
Fix
This is generally robust for stable chains like Base. No direct action is required, but it's a consideration for deployment on new or less stable networks, or if the contract were to be forked to a chain with a different ID, as it would necessitate re-issuing signatures.
Status
Unresolved
InfoSingle-Use Upgrade Initialization Function
The initializeV2_2 function includes a require(_initializedVersion == 2); check, ensuring it can only be called once and only when the previous version was correctly initialized. This is a standard and secure pattern for upgradeable contracts. However, if the initialization process were to fail mid-execution (e.g., due to an out-of-gas error or an unexpected revert within the accountsToBlacklist loop), the function could not be retried, potentially leaving the contract in an inconsistent state (7.7 Upgrades, 7.8 Operations).I-01
Issue
The initializeV2_2 function includes a require(_initializedVersion == 2); check, ensuring it can only be called once and only when the previous version was correctly initialized. This is a standard and secure pattern for upgradeable contracts. However, if the initialization process were to fail mid-execution (e.g., due to an out-of-gas error or an unexpected revert within the accountsToBlacklist loop), the function could not be retried, potentially leaving the contract in an inconsistent state (7.7 Upgrades, 7.8 Operations).
Fix
Ensure that the accountsToBlacklist array is processed efficiently and within gas limits, especially for large lists. Consider robust pre-deployment testing of the upgrade path on a testnet with realistic data to minimize the risk of failure during the single allowed execution.
Status
Unresolved
Analysis
AI Copilotas of audit · Sep 4The technical architecture (7.1) is robust, leveraging an upgradeable proxy pattern and EIP-712 for off-chain signed transactions. Code security (7.2) is generally strong, with appropriate checks for reentrancy and integer overflows, and a specific check in receiveWithAuthorization to prevent front-running. However, the custom bitmasking for balance and blacklist status in _setBlacklistState introduces complexity, which, while seemingly correct, is a non-standard pattern that requires careful management.
The economic model (7.4) is that of a centralized stablecoin, backed by fiat reserves, which inherently carries a high level of governance risk (7.5). Critical functions such as blacklisting, pausing, and upgrades are controlled by privileged addresses, typically EOAs or multi-signature wallets. This centralization, while expected for a stablecoin, means a compromise of these keys could lead to significant operational disruption or asset control issues. For example, the initializeV2_2 function allows for symbol updates and migration of blacklisted accounts, controlled by an authorized entity.
The contract utilizes a ZeppelinOS legacy proxy pattern, allowing for seamless upgrades of the token logic (7.7). The initializeV2_2 function is designed for a controlled, single-time execution during an upgrade, ensuring proper state migration and versioning. However, the proxy's admin address is an EOA, which represents a single point of failure for upgrade control. While the implementation contract itself is well-designed for upgrades, the security of the proxy admin is paramount.
It is recommended to enhance the security posture of critical administrative roles, particularly the proxy admin, by transitioning from a single EOA to a robust multi-signature wallet with a high threshold or a time-locked governance mechanism.
Thorough internal documentation for the custom blacklist storage mechanism should be maintained to mitigate future integration risks. Additionally, ensure comprehensive testing of upgrade paths on testnets, especially for functions involving state migrations like initializeV2_2, to prevent potential issues during live deployments.
Contract & Record
Free for any token on the record. It links to this page and always shows the current score and the date it was checked.
- Sep 4, 202655Medium
- Jul 28, 202660Medium
- Jul 24, 202676High
Score changes are recorded as dated snapshots — history is append-only and cannot be edited.
Would You Like a More Detailed Audit of EURC?
Our AI-powered scanner gives you a deeper, real-time smart contract analysis — free, with every scoring factor shown.
Get Detailed Audit Is this your token? Publish your own audit on this page