Quantum Audit Logo

Is Frankencoin Safe?

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

Is this your token? Publish your own audit on this page →

Frankencoin ZCHF
0xb58e…21cb
Ethereum Not verifiedLast checked 1d ago 1 audit on record
How is this score calculated? → Critical Risk
Executive SummaryAI Copilot

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.

1 Critical1 High2 Medium1 Low1 Informational
Volume 24h
$151.5K
Liquidity
$1.41M
Price
$1.2300
Token Age
2y
Top 10 Holders
90.8%

Security Findings

Critical

Inverted Minter Validity Logic

C-01The `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)
IssueThe `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)
FixChange 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.
StatusUnresolved
High

Centralized Initialization Vulnerability

H-01The `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)
IssueThe `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)
FixImplement 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.
StatusUnresolved
Medium

Potential Division by Zero in `calculateFreedAmount`

M-01The `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)
IssueThe `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)
FixAdd 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).
StatusUnresolved
Medium

Undefined External Governance Dependency

M-02The `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)
IssueThe `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)
FixProvide 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.
StatusUnresolved
Low

Minter Application Fee in ZCHF

L-01The `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)
IssueThe `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)
FixDocument 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.
StatusUnresolved
Info

Unlimited Allowance for Privileged Roles

I-01The 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)
IssueThe 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)
FixAcknowledge 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.
StatusUnresolved

Category Ratings

TechnicalMedium5/10

The 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.

GovernanceHigh1/10

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.

UpgradesHigh2/10

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.

Security Checklist

Contract VerifiedPass
Ownership Renounced?
No Mint FunctionFail
Liquidity LockedFail
Not a ProxyPass
HoneypotNoneBuy Tax0.0%Sell Tax0.0%

Holder Composition

3.1% in wallets87.6% in contracts
Effective Concentration38.2%

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.

Liquidity Depth

The risk score reads depth across every pair. The volume figure and the volume-to-liquidity ratio elsewhere on this page describe only the pair this audit analysed, so the two are not directly comparable.

LP Distribution

Top-1 Unlocked Holder100.0%
Top-3 Unlocked100.0%

Key Addresses

Deployer
0x58f1…9629
Unlocked LP Held By
0x32a5…3c26

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

What Raised This Score

  • 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

Related Audits

Global Dollar (USDG)Critical RiskBigShortBets (BIGSB)Critical RiskRe Protocol reUSD (REUSD)Critical RiskRallyCritical RiskTurtleCritical RiskSyrup Token (SYRUP)Critical Risk

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