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.
On-chain security analysis — is it a scam or legit?
Is Curve DAO Token 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 →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- 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 4Holders
as of audit · Sep 4, 2026- Contractstreasury, vesting, bridge, staking13.2%
- Walletsanonymous holders, free to sell50.1%
- Everyone elsethe rest of the supply36.7%
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- UniswapWETHAnalysed$495.4K95.1%
- UniswapWETH$9.0K1.7%
- SushiswapWETH$8.4K1.6%
- UniswapUSDC$5.9K1.1%
- SwaprWETH$8020.2%
- PancakeswapWETH$5340.1%
One more pair holds $4 and is 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.
0x33ab…21fa0x7a48…911c0x55ac…e1490x60c6…10810x1540…813d0xf8d0…dd0c0xdec1…63760x1bac…d8070x4e24…25100x841e…153fNo privileged address appears among these holders: the unlocked liquidity sits with independent providers, not with the deployer.
Security Findings
CriticalCloneable 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
Cloneable contract's isMasterCopy state variable is not correctly initialized in proxy contextIssue
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
HighUnprotected 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
bridgeInit allows anyone to set l2GatewayIssue
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
MediumPotential 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
decimals, name, symbol getters to revertIssue
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
LowBytesParser.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
BytesParser.toString logic for input.length == 32 is complex and potentially error-proneIssue
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
InfoImplicit 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
BytesParser.toStringIssue
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 4The 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).
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).
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).
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
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, 202664Medium
- 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