The audit of the Frankencoin protocol identified a critical logic error in the isMinter function, which inverts minter validity and prevents core functionality. A high-severity access control flaw in the initialize function allows for front-running. Additionally, potential division by zero, reliance on an unaudited external governance contract, and economic design considerations were noted. The protocol's core functionality is significantly impacted by the critical bug.

On-chain security analysis — is it a scam or legit?
Is Frankencoin 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 Frankencoin protocol identified a critical logic error in the isMinter function, which inverts minter validity and prevents core functionality.
- Ownership status UNKNOWN
- Mintable supply — no cap found, dilution unbounded
- Top-10 concentration > 30%
- Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
- LP top1 unlocked holder = 100.0%
- LP top3 unlocked holders = 100.0%
- 1 Critical finding(s) from audit
- 1 High finding(s) from audit
- 2 Medium finding(s) from audit
- 1 Low finding(s) from audit
Exact factors
- Ownership status UNKNOWN (owner could not be resolved)
- Mintable supply — no cap found, dilution unbounded
- Top-10 concentration > 30% (90.8% total → 38.2% effective; 3.1% in EOAs, 87.6% in contracts — moderate)
- Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
- LP top1 unlocked holder = 100.0% (independent LP — depth risk, pool = 67% of DEX liquidity)
- LP top3 unlocked holders = 100.0% (independent LP — depth risk, pool = 67% of DEX liquidity)
- 1 Critical finding(s) from audit
- 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
Security Checklist
as of audit · Sep 5Holders
as of audit · Sep 5, 2026- Contractstreasury, vesting, bridge, staking87.6%
- Walletsanonymous holders, free to sell3.1%
- Everyone elsethe rest of the supply9.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 5, 2026
Liquidity
as of audit · Sep 5- Uniswap v3USDTAnalysed$1.41M67.1%
- Uniswap v4XAN$482.6K22.9%
- Uniswap v3WETH$188.3K8.9%
- Uniswap v4EURC$21.4K1.0%
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.
0x32a5…3c26No privileged address appears among these holders: the unlocked liquidity sits with independent providers, not with the deployer.
Security Findings
CriticalInverted Minter Validity Logic
The isMinter function, which controls access to critical minter-only functions, uses the condition block.timestamp >= minters[_minter]. However, minters[_minter] is set to block.timestamp + _applicationPeriod in suggestMinter (and block.timestamp in initialize), indicating it stores the *end* timestamp of the validity period. This means a minter is only considered valid *after* their application period has expired, effectively preventing them from performing minter actions during their intended active period. This renders the core minter functionality unusable. (7.2 Code Security)C-01
Issue
The isMinter function, which controls access to critical minter-only functions, uses the condition block.timestamp >= minters[_minter]. However, minters[_minter] is set to block.timestamp + _applicationPeriod in suggestMinter (and block.timestamp in initialize), indicating it stores the *end* timestamp of the validity period. This means a minter is only considered valid *after* their application period has expired, effectively preventing them from performing minter actions during their intended active period. This renders the core minter functionality unusable. (7.2 Code Security)
Fix
Change the condition in isMinter to block.timestamp < minters[_minter] to correctly reflect that a minter is valid *during* their application period. Ensure this change is thoroughly tested.
Status
Unresolved
HighCentralized Initialization Vulnerability
The initialize function, which sets the initial minter, lacks access control and can be called by any address as long as totalSupply() and reserve.totalSupply() are zero. This creates a front-running vulnerability where an attacker could call initialize before the legitimate deployer, setting themselves as the initial minter and gaining unauthorized control over the protocol's initial state. (7.3 Access Control)H-01
Issue
The initialize function, which sets the initial minter, lacks access control and can be called by any address as long as totalSupply() and reserve.totalSupply() are zero. This creates a front-running vulnerability where an attacker could call initialize before the legitimate deployer, setting themselves as the initial minter and gaining unauthorized control over the protocol's initial state. (7.3 Access Control)
Fix
Implement an onlyOwner or similar access control mechanism for the initialize function, ensuring only the intended deployer can call it. Alternatively, consider setting the initial minter directly in the constructor if possible.
Status
Unresolved
MediumPotential Division by Zero in calculateFreedAmount
The calculateFreedAmount function includes a division by (1000000 - adjustedReservePPM). If adjustedReservePPM were to equal 1000000 (e.g., if reservePPM is set to 1,000,000 and currentReserve >= minterReserve_), this would result in a division-by-zero error, causing transactions to revert. While PPM (parts per million) typically implies values less than 1,000,000, there's no explicit upper bound check for reservePPM or adjustedReservePPM to prevent this. (7.2 Code Security)M-01
calculateFreedAmountIssue
The calculateFreedAmount function includes a division by (1000000 - adjustedReservePPM). If adjustedReservePPM were to equal 1000000 (e.g., if reservePPM is set to 1,000,000 and currentReserve >= minterReserve_), this would result in a division-by-zero error, causing transactions to revert. While PPM (parts per million) typically implies values less than 1,000,000, there's no explicit upper bound check for reservePPM or adjustedReservePPM to prevent this. (7.2 Code Security)
Fix
Add a check to ensure adjustedReservePPM is strictly less than 1000000 before performing the division, or handle the edge case where it equals 1000000 gracefully (e.g., by reverting with a specific error or returning a maximum value).
Status
Unresolved
MediumUndefined External Governance Dependency
The denyMinter function critically relies on reserve.checkQualified(msg.sender, _helpers). The implementation of checkQualified within the Equity contract (acting as the reserve) is not provided in the audited code. This creates an opaque dependency on an external contract's logic, specifically its governance or access control mechanisms. The security and decentralization of the Frankencoin protocol are thus directly tied to the (unseen) implementation of Equity.checkQualified. (7.6 External, 7.5 Governance)M-02
Issue
The denyMinter function critically relies on reserve.checkQualified(msg.sender, _helpers). The implementation of checkQualified within the Equity contract (acting as the reserve) is not provided in the audited code. This creates an opaque dependency on an external contract's logic, specifically its governance or access control mechanisms. The security and decentralization of the Frankencoin protocol are thus directly tied to the (unseen) implementation of Equity.checkQualified. (7.6 External, 7.5 Governance)
Fix
Provide the full source code for the Equity contract, especially the checkQualified function, for a complete security assessment. Clearly document the expected behavior and access control of this external dependency.
Status
Unresolved
LowMinter Application Fee in ZCHF
The suggestMinter function requires applicants to pay an _applicationFee in ZCHF, which is transferred to the reserve via _collectProfits. This design choice means that prospective minters must first acquire ZCHF to apply, potentially creating a barrier to entry or requiring an initial distribution mechanism for the token. (7.4 Economic)L-01
Issue
The suggestMinter function requires applicants to pay an _applicationFee in ZCHF, which is transferred to the reserve via _collectProfits. This design choice means that prospective minters must first acquire ZCHF to apply, potentially creating a barrier to entry or requiring an initial distribution mechanism for the token. (7.4 Economic)
Fix
Document this economic design choice clearly. Consider if alternative fee mechanisms (e.g., in a base currency like ETH or stablecoins) might be more suitable for initial bootstrapping or broader accessibility, depending on the project's goals.
Status
Unresolved
InfoUnlimited Allowance for Privileged Roles
The custom _allowance function grants an INFINITY allowance to minters, their registered position parents, and the reserve contract. While this simplifies operations for these trusted entities by removing the need for repeated approvals, it also means that a compromise of a minter's private key or a vulnerability in the reserve contract could lead to unlimited spending of their ZCHF balance. (7.3 Access Control)I-01
Issue
The custom _allowance function grants an INFINITY allowance to minters, their registered position parents, and the reserve contract. While this simplifies operations for these trusted entities by removing the need for repeated approvals, it also means that a compromise of a minter's private key or a vulnerability in the reserve contract could lead to unlimited spending of their ZCHF balance. (7.3 Access Control)
Fix
Acknowledge this design decision and ensure that robust security practices are in place for managing minter keys and the reserve contract. Consider if a configurable, high but not infinite, allowance might offer a better balance of convenience and security for minters, or if specific allowances for specific operations could be implemented.
Status
Unresolved
Analysis
AI Copilotas of audit · Sep 5The technical architecture is generally sound, leveraging ERC20PermitLight and custom reserve mechanics. However, a critical logic error in the isMinter function (7.2 Code Security) inverts minter validity, rendering core minter functions unusable. A high-severity access control flaw in the initialize function (7.3 Access Control) allows for front-running. Additionally, a potential division by zero in calculateFreedAmount (7.2 Code Security) could lead to transaction reverts.
The Frankencoin protocol incorporates a reserve mechanism and a system for minter management, including the ability to mint ZCHF to cover losses (7.4 Economic). The denyMinter function relies on an external Equity contract's checkQualified function (7.5 Governance, 7.6 External), introducing a dependency on its (unaudited) governance logic. The requirement for minters to pay an application fee in ZCHF (7.4 Economic) could impact accessibility.
The Frankencoin contract is not designed with an upgradeability mechanism (7.7 Upgrades). It is deployed as a standard, non-proxy contract, meaning its logic cannot be changed post-deployment. This eliminates upgrade-related risks but requires any future changes to be deployed as a new contract.
Prioritize immediate resolution of the critical isMinter logic error and the initialize function's access control vulnerability to ensure the protocol's fundamental operations are secure and functional.
Conduct a thorough review of all mathematical operations, especially those involving division, to prevent potential reverts. Furthermore, a comprehensive audit of the Equity contract, particularly its checkQualified function, is essential to understand and mitigate the risks associated with its governance dependency.
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 5, 202681High
Score changes are recorded as dated snapshots — history is append-only and cannot be edited.
Frequently Asked Questions
What is the ZCHF contract address?
The Frankencoin (ZCHF) contract on Ethereum is 0xb58e61c3098d85632df34eecfb899a1ed80921cb. Compare it with the address the project itself publishes before trading: other contracts can carry the same name and ticker.
Is Frankencoin a scam?
Quantum Audit's risk score for Frankencoin is 81/100 (High risk) as of Sep 5, 2026, computed by a deterministic function from on-chain facts — Contract verified: Verified; Mint: Mintable; Liquidity lock: Not locked; Upgradeability: Fixed code; 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 ZCHF liquidity locked?
Liquidity lock: Not locked (as of Sep 5, 2026). Total DEX liquidity: $2.10M.
Who holds ZCHF?
As of Sep 5, 2026, the 10 largest holders own 90.8% of the supply. The Holders section on this page shows who they are by holder type.
Would You Like a More Detailed Audit of Frankencoin?
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