The audit of the StandardArbERC20 implementation contract, used via a ClonableBeaconProxy, identified a High-severity access control vulnerability related to the initialization of cloned token instances. Additionally, Medium and Low severity issues were found concerning ERC20 standard compliance and parsing logic. The contract generally demonstrates good architectural patterns for an L2 bridged token, leveraging OpenZeppelin libraries and a beacon proxy for upgradeability. However, critical attention is required for the initialization process of new token clones to prevent unauthorized control.
On-chain security analysis — is it a scam or legit?
Is MAGIC 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 implementation contract, used via a ClonableBeaconProxy, identified a High-severity access control vulnerability related to the initialization of cloned token instances.
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
- LP top1 unlocked holder = 55.2%
- LP top3 unlocked holders = 82.9%
- 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% (66.3% total → 66.3% effective; 66.3% in EOAs, 0.0% in contracts — heavy)
- Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
- LP top1 unlocked holder = 55.2% (independent LP — depth risk, pool = 79% of DEX liquidity)
- LP top3 unlocked holders = 82.9% (independent LP — depth risk, pool = 79% of DEX liquidity)
- 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- Walletsanonymous holders, free to sell66.3%
- Everyone elsethe rest of the supply33.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- SushiswapWETHAnalysed$177.4K79.4%
- UniswapWETH$24.9K11.2%
- Camelot v3WETH$15.9K7.1%
- Sushiswap v3WETH$2.3K1.0%
- UniswapWETH$2.0K0.9%
- OreoswapWETH$3900.2%
The 4 remaining pairs hold $23 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.
0x3887…7f1c0xdb6a…e2330x8f28…514e0x4e3b…d42e0x7c2d…d4370xf2e1…048e0x0856…0af80x378f…ec920xd510…20e40x84d9…39caNo privileged address appears among these holders: the unlocked liquidity sits with independent providers, not with the deployer.
Security Findings
HighUnprotected bridgeInit Allows Malicious Initialization of Clones
The bridgeInit function, which serves as the initializer for each cloned token instance, is declared as public without any access control. While L2GatewayToken._initialize prevents re-initialization of state variables within a single clone, the *first* caller to bridgeInit on a newly deployed clone can set the l2Gateway and l1Address. A malicious actor could front-run the legitimate gateway deployment or initialization, setting themselves as the l2Gateway, thereby gaining unauthorized control over bridgeMint and bridgeBurn functions for that specific token instance. This compromises the integrity of the token supply for affected clones (7.3 Access Control, 7.2 Code Securit…H-01
bridgeInit Allows Malicious Initialization of ClonesIssue
The bridgeInit function, which serves as the initializer for each cloned token instance, is declared as public without any access control. While L2GatewayToken._initialize prevents re-initialization of state variables within a single clone, the *first* caller to bridgeInit on a newly deployed clone can set the l2Gateway and l1Address. A malicious actor could front-run the legitimate gateway deployment or initialization, setting themselves as the l2Gateway, thereby gaining unauthorized control over bridgeMint and bridgeBurn functions for that specific token instance. This compromises the integrity of the token supply for affected clones (7.3 Access Control, 7.2 Code Securit…
Fix
Implement an onlyInitializing or similar modifier to restrict calls to bridgeInit to a trusted entity (e.g., the deployer, a factory contract, or a designated initializer role). This ensures that only the intended party can configure the critical l2Gateway and l1Address for new token clones.
Status
Unresolved
MediumERC20 Standard Functions (name, symbol, decimals) Can Revert
The name(), symbol(), and decimals() functions can revert if the corresponding ignore flags (ignoreName, ignoreSymbol, ignoreDecimals) are set to true during bridgeInit. These flags are set if the BytesParser fails to parse the provided _data for name, symbol, or decimals. This behavior deviates from the standard ERC20 interface, where these functions are expected to always return a value. Integrations relying on these functions might break if they do not handle reverts gracefully, leading to a denial of service for metadata retrieval (7.2 Code Security).M-01
name, symbol, decimals) Can RevertIssue
The name(), symbol(), and decimals() functions can revert if the corresponding ignore flags (ignoreName, ignoreSymbol, ignoreDecimals) are set to true during bridgeInit. These flags are set if the BytesParser fails to parse the provided _data for name, symbol, or decimals. This behavior deviates from the standard ERC20 interface, where these functions are expected to always return a value. Integrations relying on these functions might break if they do not handle reverts gracefully, leading to a denial of service for metadata retrieval (7.2 Code Security).
Fix
Consider returning default or empty values (e.g., empty string for name/symbol, 0 for decimals) instead of reverting when parsing fails. Alternatively, ensure robust validation of _data during bridgeInit to prevent these flags from being set unnecessarily, or provide a mechanism for a privileged role to correct the metadata if parsing initially fails.
Status
Unresolved
LowBytesParser.toString Edge Case for 32-Byte Strings
The BytesParser.toString function has specific logic for input.length == 32. If input[31] is not bytes1(0x00), it returns (false, res), indicating a parsing failure. This means a valid 32-byte string that happens to have a non-zero last byte (e.g., 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF') would be considered a parsing failure, leading to ignoreName or ignoreSymbol being set to true. This could cause the name() or symbol() functions to revert unnecessarily, even for valid inputs (7.2 Code Security).L-01
BytesParser.toString Edge Case for 32-Byte StringsIssue
The BytesParser.toString function has specific logic for input.length == 32. If input[31] is not bytes1(0x00), it returns (false, res), indicating a parsing failure. This means a valid 32-byte string that happens to have a non-zero last byte (e.g., 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF') would be considered a parsing failure, leading to ignoreName or ignoreSymbol being set to true. This could cause the name() or symbol() functions to revert unnecessarily, even for valid inputs (7.2 Code Security).
Fix
Review the BytesParser.toString logic for 32-byte strings to ensure it correctly handles all valid string representations. If the intent is to treat 32-byte inputs as bytes32 and only convert if they are null-padded, this should be clearly documented or handled differently to avoid false negatives for valid strings.
Status
Unresolved
InfoIndirect abi.decode for String/Uint8 Parsing
In bridgeInit, the _data is first abi.decoded into three bytes variables, which are then passed to BytesParser.toString and BytesParser.toUint8. If the _data is consistently encoded as abi.encode(name, symbol, decimals), directly decoding to (string, string, uint8) might simplify the code. The current approach adds an extra parsing layer that handles specific byte representations (7.2 Code Security).I-01
abi.decode for String/Uint8 ParsingIssue
In bridgeInit, the _data is first abi.decoded into three bytes variables, which are then passed to BytesParser.toString and BytesParser.toUint8. If the _data is consistently encoded as abi.encode(name, symbol, decimals), directly decoding to (string, string, uint8) might simplify the code. The current approach adds an extra parsing layer that handles specific byte representations (7.2 Code Security).
Fix
Document the expected encoding format for _data. If the _data is always abi.encode(name, symbol, decimals), consider direct abi.decode(_data, (string, string, uint8)) for simplicity. If the bytes inputs are expected to be arbitrary byte sequences requiring specific parsing logic (e.g., 32-byte fixed-length strings), the current approach is justified, but the parsing logic should be robust and well-documented.
Status
Unresolved
InfoTransferAndCallToken Uses extcodesize for isContract Check
The isContract function in TransferAndCallToken uses extcodesize to determine if an address is a contract. A known edge case with extcodesize is that it returns 0 during a contract's constructor execution. This means if transferAndCall is called to an address that is currently in its constructor, isContract would return false, and the onTokenTransfer callback would not be invoked (7.2 Code Security).I-02
TransferAndCallToken Uses extcodesize for isContract CheckIssue
The isContract function in TransferAndCallToken uses extcodesize to determine if an address is a contract. A known edge case with extcodesize is that it returns 0 during a contract's constructor execution. This means if transferAndCall is called to an address that is currently in its constructor, isContract would return false, and the onTokenTransfer callback would not be invoked (7.2 Code Security).
Fix
Be aware of this EVM quirk. For most scenarios, this is not an issue as transferAndCall is typically used with already deployed contracts. If interaction with contracts during their construction phase is a critical use case, alternative checks or design patterns might be necessary.
Status
Unresolved
Analysis
AI Copilotas of audit · Sep 4The StandardArbERC20 contract implements an L2 bridged ERC20 token, utilizing OpenZeppelin's upgradeable ERC20 standard and a Cloneable pattern for efficient deployment. Key strengths include the onlyGateway modifier for bridgeMint and bridgeBurn functions, ensuring controlled token supply management (7.3 Access Control). However, a significant vulnerability exists in the bridgeInit function, which is public and unprotected, allowing any caller to initialize a new clone and potentially set a malicious l2Gateway (7.3 Access Control, 7.2 Code Security). Furthermore, the name(), symbol(), and decimals() functions can revert if parsing fails during initialization, deviating from standard ERC20 behavior and potentially breaking integrations (7.2 Code Security).
This contract primarily functions as an L2 token implementation and does not contain direct governance mechanisms or complex economic models. Its economic security is largely tied to the integrity of the Arbitrum bridge and the L2 Gateway, which are external components. The bridgeMint and bridgeBurn functions are appropriately restricted to the l2Gateway, mitigating direct economic manipulation within the token contract itself (7.4 Economic, 7.5 Governance).
The contract is designed as an implementation for a ClonableBeaconProxy, enabling efficient deployment of multiple token instances and facilitating future upgrades via the beacon. The _initialize function includes a check (ALREADY_INIT) to prevent re-initialization of critical state variables within a single clone (7.7 Upgrades). However, the bridgeInit function, which triggers this initialization, lacks access control, creating a window for malicious actors to front-run the legitimate initializer for new clones (7.7 Upgrades, 7.3 Access Control).
Prioritize implementing robust access control for the bridgeInit function to ensure only authorized entities can initialize new token clones.
This is crucial for preventing unauthorized control over token minting and burning capabilities. Additionally, review the behavior of name(), symbol(), and decimals() to align with ERC20 standards, potentially by returning default values instead of reverting on parsing failures. Finally, refine the BytesParser.toString logic to handle edge cases more gracefully, ensuring consistent token metadata availability.
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.
- Aug 31, 202658Medium
Score changes are recorded as dated snapshots — history is append-only and cannot be edited.
Frequently Asked Questions
What is the MAGIC contract address?
The MAGIC contract on Arbitrum is 0x539bde0d7dbd336b79148aa742883198bbf60342. Compare it with the address the project itself publishes before trading: other contracts can carry the same name and ticker.
Is MAGIC a scam?
Quantum Audit's risk score for MAGIC is 58/100 (Medium risk) as of Sep 4, 2026, computed by a deterministic function from on-chain facts — Contract verified: Verified; Mint: No mint; Liquidity lock: Not locked; Upgradeability: Upgradeable; Honeypot: None found; Buy / sell tax: 0% / 0%. A score is a dated snapshot of those facts, not a guarantee; each one is listed on this page.
Is MAGIC liquidity locked?
Liquidity lock: Not locked (as of Sep 4, 2026). Total DEX liquidity: $223.4K.
Who holds MAGIC?
As of Sep 4, 2026, the 10 largest holders own 66.3% of the supply. The Holders section on this page shows who they are by holder type.
Would You Like a More Detailed Audit of MAGIC?
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