Quantum Audit Logo
Launch App

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

Is Curve DAO Token Safe?

CRVArbitrum
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 →
Last checked Sep 4, 2026 · 1 audit on record
SummaryAI Copilot

The audit of the StandardArbERC20 contract, serving as an L2 token implementation for the Arbitrum bridge, identified critical and high-severity issues primarily related to initialization and proxy compatibility.

Read the full analysis
What raised the score
  • Ownership status UNKNOWN
  • Proxy contract
  • Complex proxy pattern
  • Top-10 concentration > 50%
  • 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
  • 1 Low finding(s) from audit
Exact factors
  • Ownership status UNKNOWN (owner could not be resolved)
  • Proxy contract (upgradeable — admin can replace logic)
  • Complex proxy pattern (BEACON)
  • Top-10 concentration > 50% (63.3% total → 55.4% effective; 50.1% in EOAs, 13.2% in contracts — heavy)
  • 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
  • 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

Security Checklist

as of audit · Sep 42 of 5 checks passed
Contract verifiedVerified
OwnershipUnknown
MintNo mint
Liquidity lockNot locked
UpgradeabilityUpgradeable

Holders

as of audit · Sep 4, 2026
13.2%Contracts50.1%Wallets36.7%Everyone else
13.2%50.1%Wallets36.7%Everyone else
ContractsWalletsEveryone elseBubble area = share of supply
63.3%of supply sits with the top 10 holders
  • Contractstreasury, vesting, bridge, staking13.2%
  • Walletsanonymous holders, free to sell50.1%
  • Everyone elsethe rest of the supply36.7%
Effective concentrationwhat the score reads55.4%
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$521.0K across 11 pairs
LP tokensNot locked

The LP tokens of the analysed pool are not locked or burned, so whoever holds them can withdraw that liquidity.

Analysed pool$495.4KShare of depth95.1%
Top-1 Unlocked Holder24.2%
Top-3 Unlocked37.6%
Unlocked LP held by
0x33ab…21fa0x7a48…911c0x55ac…e1490x60c6…10810x1540…813d0xf8d0…dd0c0xdec1…63760x1bac…d8070x4e24…25100x841e…153f

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

Security Findings

1 Critical1 High1 Medium1 Low1 Info
Critical

Cloneable contract's isMasterCopy state variable is not correctly initialized in proxy context

The Cloneable contract uses a constructor to set isMasterCopy = true. In a proxy pattern (like ClonableBeaconProxy), the constructor is only executed on the *implementation* contract, not on the *proxy* contract. State variables for the proxy are stored in the proxy's storage. Therefore, isMasterCopy in the proxy's storage will remain its default value (false). This means the safeSelfDestruct function, which has a require(!isMasterCopy, NOT_CLONE);, will *not* revert for a proxy. A malicious actor could potentially call safeSelfDestruct on a proxy contract, leading to its destruction and loss of all associated funds/functionality.C-01

Issue

The Cloneable contract uses a constructor to set isMasterCopy = true. In a proxy pattern (like ClonableBeaconProxy), the constructor is only executed on the *implementation* contract, not on the *proxy* contract. State variables for the proxy are stored in the proxy's storage. Therefore, isMasterCopy in the proxy's storage will remain its default value (false). This means the safeSelfDestruct function, which has a require(!isMasterCopy, NOT_CLONE);, will *not* revert for a proxy. A malicious actor could potentially call safeSelfDestruct on a proxy contract, leading to its destruction and loss of all associated funds/functionality.

Fix

The Cloneable pattern is incompatible with standard proxy patterns for managing isMasterCopy as a state variable. The safeSelfDestruct function should be removed from the proxy's callable interface, or the isMasterCopy check needs to be re-architected to be compatible with upgradeable proxies (e.g., by using a storage slot explicitly initialized in the _initialize function).

Status

Unresolved

High

Unprotected bridgeInit allows anyone to set l2Gateway

The bridgeInit function is public virtual and can be called by anyone. It calls L2GatewayToken._initialize, which sets the critical l2Gateway and l1Address parameters. While _initialize includes an ALREADY_INIT check, a malicious actor could front-run the legitimate initializer and set themselves as the l2Gateway. This would grant them full control over bridgeMint and bridgeBurn, allowing them to mint tokens to arbitrary addresses or burn existing tokens.H-01

Issue

The bridgeInit function is public virtual and can be called by anyone. It calls L2GatewayToken._initialize, which sets the critical l2Gateway and l1Address parameters. While _initialize includes an ALREADY_INIT check, a malicious actor could front-run the legitimate initializer and set themselves as the l2Gateway. This would grant them full control over bridgeMint and bridgeBurn, allowing them to mint tokens to arbitrary addresses or burn existing tokens.

Fix

Implement a robust access control mechanism for the bridgeInit function, such as an onlyOwner modifier or a specific initializer role, to ensure that only a trusted entity can call it. This is crucial to prevent unauthorized control of the L2 gateway.

Status

Unresolved

Medium

Potential for decimals, name, symbol getters to revert

The StandardArbERC20 contract allows ignoreDecimals, ignoreName, ignoreSymbol to be set to true during bridgeInit if the parsing of the L1 token metadata fails. If these flags are true, calling the respective standard ERC20 getter (decimals(), name(), symbol()) will cause a revert(). This behavior, while potentially intended to signal invalid L1 data, can lead to unexpected reverts for users or dApps trying to interact with the token, potentially breaking integrations that rely on these standard ERC20 getters.M-01

Issue

The StandardArbERC20 contract allows ignoreDecimals, ignoreName, ignoreSymbol to be set to true during bridgeInit if the parsing of the L1 token metadata fails. If these flags are true, calling the respective standard ERC20 getter (decimals(), name(), symbol()) will cause a revert(). This behavior, while potentially intended to signal invalid L1 data, can lead to unexpected reverts for users or dApps trying to interact with the token, potentially breaking integrations that rely on these standard ERC20 getters.

Fix

Consider returning default or empty values (e.g., 0 for decimals, empty string for name/symbol) instead of reverting when ignore* flags are set. Alternatively, ensure that the L1 data parsing is robust enough to minimize failures, or provide a clear error message in the revert reason.

Status

Unresolved

Low

BytesParser.toString logic for input.length == 32 is complex and potentially error-prone

The BytesParser.toString function contains specific logic for input.length == 32 that attempts to truncate trailing null bytes. This logic involves a loop and an assembly block to create a new, truncated bytes array. While aiming to handle a specific encoding, this approach adds complexity and potential for off-by-one errors or misinterpretations of byte data compared to a simpler abi.decode(input, (string)) for all non-zero length inputs.L-01

Issue

The BytesParser.toString function contains specific logic for input.length == 32 that attempts to truncate trailing null bytes. This logic involves a loop and an assembly block to create a new, truncated bytes array. While aiming to handle a specific encoding, this approach adds complexity and potential for off-by-one errors or misinterpretations of byte data compared to a simpler abi.decode(input, (string)) for all non-zero length inputs.

Fix

Simplify the toString logic if possible, or add comprehensive unit tests specifically for the input.length == 32 case with various byte patterns (e.g., all nulls, partial nulls, no nulls, non-ASCII characters) to ensure correctness and robustness.

Status

Unresolved

Info

Implicit assumption of valid ABI-encoded strings in BytesParser.toString

The BytesParser.toString function uses abi.decode(input, (string)) for input.length != 0 && input.length != 32. This implicitly assumes that the input bytes are always valid ABI-encoded strings. If input contains arbitrary bytes that are not valid ABI-encoded strings, abi.decode might revert or produce unexpected results, leading to runtime errors or incorrect data interpretation.I-01

Issue

The BytesParser.toString function uses abi.decode(input, (string)) for input.length != 0 && input.length != 32. This implicitly assumes that the input bytes are always valid ABI-encoded strings. If input contains arbitrary bytes that are not valid ABI-encoded strings, abi.decode might revert or produce unexpected results, leading to runtime errors or incorrect data interpretation.

Fix

Add more robust validation or error handling around abi.decode(input, (string)) to ensure the input bytes represent a valid string, or clarify the expected encoding of the input bytes in the function's documentation.

Status

Unresolved

Analysis

AI Copilotas of audit · Sep 4
Executive SummaryWhat the contract is and what the review found

The audit of the StandardArbERC20 contract, serving as an L2 token implementation for the Arbitrum bridge, identified critical and high-severity issues primarily related to initialization and proxy compatibility. The bridgeInit function lacks proper access control, allowing potential front-running to seize control of minting/burning. A critical flaw exists in the Cloneable contract's interaction with the proxy pattern, potentially enabling self-destruction of proxy instances. Several minor issues related to code quality and getter behavior were also noted.

Technical6/10Medium risk

The technical architecture leverages OpenZeppelin upgradeable contracts and custom libraries for byte parsing, demonstrating a structured approach (7.1 Architecture). The bridgeMint and bridgeBurn functions are correctly protected by an onlyGateway modifier (7.3 Access Control). However, a critical vulnerability exists where the Cloneable contract's isMasterCopy state is not correctly initialized in the proxy context, potentially allowing proxies to be self-destructed (7.2 Code Security, 7.7 Upgrades). Additionally, the bridgeInit function lacks proper access control, enabling a front-running attack to control the L2 gateway (7.3 Access Control).

Governance1/10High risk

The economic model relies on the l2Gateway to control token minting and burning, which is standard for an L2 bridge token (7.4 Economic). The l2Gateway address is set during initialization, making its initial security paramount. The StandardArbERC20 contract's decimals, name, and symbol getters can revert if L1 metadata parsing fails, which could negatively impact user experience and dApp integrations (7.4 Economic). There is no explicit governance mechanism beyond the l2Gateway's control (7.5 Governance).

Upgrades1/10High risk

The contract utilizes a ClonableBeaconProxy pattern, indicating an intention for upgradeability (7.7 Upgrades). The _initialize pattern is correctly used for state initialization in the upgradeable context. However, the Cloneable base contract's isMasterCopy state variable is initialized via a constructor, which is incompatible with the proxy pattern. This critical flaw means isMasterCopy will be false in proxy instances, potentially allowing safeSelfDestruct to be called on live proxies, leading to catastrophic loss of functionality and assets (7.7 Upgrades).

Final RecommendationWhat to do about this score

Address the critical Cloneable contract incompatibility with the proxy pattern immediately, either by removing safeSelfDestruct or re-architecting isMasterCopy for upgradeable contexts.

Implement robust access control for the bridgeInit function to prevent unauthorized control of the L2 gateway. Review and refine the BytesParser logic for string and uint8 conversions, particularly the handling of input.length == 32 and arbitrary byte inputs, to enhance robustness and prevent unexpected reverts.

Contract & Record

1 audit on record
TypeClonableBeaconProxy
NetworkArbitrum
Token age4y
Contract0x11cd…4978
Deployer0x3fe3…000f
Proxy Upgrade Controls
Proxy TypeBeacon
ImplementationVerified source
Upgrades (30d)0 · stable
Badge for your website
Curve DAO Token security record badge

Free for any token on the record. It links to this page and always shows the current score and the date it was checked.

Audit History
  1. Sep 4, 202664Medium
  2. Aug 11, 202670High

Score changes are recorded as dated snapshots — history is append-only and cannot be edited.

Would You Like a More Detailed Audit of Curve DAO Token?

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