Quantum Audit Logo

Is Trace Token Safe?

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

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

Trace Token TRAC
0xaa7a…0a6f
Ethereum Not verifiedLast checked 3d ago 1 audit on record
Executive SummaryAI Copilot

The TracToken contract is an ERC-20 compliant token with minting and vesting functionalities. While it incorporates SafeMath for arithmetic safety and includes mechanisms to prevent the ERC20 approve race condition, it operates on an outdated Solidity compiler version. A critical vulnerability exists where the contract owner can mint an unlimited supply of tokens, exceeding the stated TOTAL_NUM_TOKENS, which severely impacts tokenomics. Additionally, the owner retains significant control over token supply and transferability, posing a high centralization risk. Vesting schedules rely on block timestamps and are dependent on the owner enabling transfers, introducing potential delays for beneficiaries.

1 Critical1 High2 Medium2 Low2 Informational
Volume 24h
$90.7K
Liquidity
$410.6K
Price
$0.3373
Token Age
5y
Top 10 Holders
51.3%

Security Findings

Critical

Owner Can Mint Tokens Beyond `TOTAL_NUM_TOKENS` Limit

C-01The `MintableToken.mint` function, which is called by `TracToken.mint`, does not include a check to ensure that the `totalSupply` does not exceed the `TOTAL_NUM_TOKENS` constant defined in `TracToken`. While `allocateRestOfTokens` has a `require(totalSupply < TOTAL_NUM_TOKENS)` check, this only applies before that specific function call. The owner can directly call `mint` multiple times, or after `allocateRestOfTokens`, to inflate the total supply beyond the intended maximum, severely devaluing existing tokens.
IssueThe `MintableToken.mint` function, which is called by `TracToken.mint`, does not include a check to ensure that the `totalSupply` does not exceed the `TOTAL_NUM_TOKENS` constant defined in `TracToken`. While `allocateRestOfTokens` has a `require(totalSupply < TOTAL_NUM_TOKENS)` check, this only applies before that specific function call. The owner can directly call `mint` multiple times, or after `allocateRestOfTokens`, to inflate the total supply beyond the intended maximum, severely devaluing existing tokens.
FixImplement a `require(totalSupply.add(_amount) <= TOTAL_NUM_TOKENS)` check within the `mint` function to enforce the maximum token supply. This check should be present in the `MintableToken.mint` function or the overridden `TracToken.mint` function.
StatusUnresolved
High

High Centralization of Control

H-01The `Ownable` pattern grants the `owner` address extensive control over critical functions, including `mint`, `finishMinting` (which enables transfers), `endMinting`, `allocateRestOfTokens`, and `transferOwnership`. This creates a single point of failure; if the owner's private key is compromised, an attacker could mint unlimited tokens, prevent transfers, or transfer ownership to themselves, leading to a complete loss of control and trust in the token.
IssueThe `Ownable` pattern grants the `owner` address extensive control over critical functions, including `mint`, `finishMinting` (which enables transfers), `endMinting`, `allocateRestOfTokens`, and `transferOwnership`. This creates a single point of failure; if the owner's private key is compromised, an attacker could mint unlimited tokens, prevent transfers, or transfer ownership to themselves, leading to a complete loss of control and trust in the token.
FixConsider implementing a multi-signature wallet (e.g., Gnosis Safe) for the `owner` address to distribute control among multiple trusted parties. For highly sensitive operations like `mint` or `finishMinting`, consider adding time-locks or a decentralized governance mechanism if feasible.
StatusUnresolved
Medium

Vesting Functions Dependent on `mintingFinished` Flag

M-01The `withdrawTokenToFounders` and `withdrawTokensToAdvisors` functions use `this.transfer`, which internally calls `TracToken.transfer`. Both `TracToken.transfer` and `TracToken.transferFrom` are guarded by the `canTransfer` modifier, which requires `mintingFinished` to be true. This means that founders and advisors cannot withdraw their vested tokens until the contract owner calls `finishMinting()` or `endMinting()`. An malicious or inactive owner could indefinitely delay these withdrawals, causing economic harm to beneficiaries.
IssueThe `withdrawTokenToFounders` and `withdrawTokensToAdvisors` functions use `this.transfer`, which internally calls `TracToken.transfer`. Both `TracToken.transfer` and `TracToken.transferFrom` are guarded by the `canTransfer` modifier, which requires `mintingFinished` to be true. This means that founders and advisors cannot withdraw their vested tokens until the contract owner calls `finishMinting()` or `endMinting()`. An malicious or inactive owner could indefinitely delay these withdrawals, causing economic harm to beneficiaries.
FixRe-evaluate the design of the vesting functions. If the intention is for vesting to occur independently of general token transferability, consider modifying `withdrawTokenToFounders` and `withdrawTokensToAdvisors` to directly update balances without calling the restricted `transfer` function, or ensure the `canTransfer` modifier is not applied to internal `this.transfer` calls within these specific vesting functions.
StatusUnresolved
Medium

Use of `block.timestamp` for Vesting Schedules

M-02The `withdrawTokenToFounders` and `withdrawTokensToAdvisors` functions use `now` (an alias for `block.timestamp`) to determine if vesting periods have passed. While common, `block.timestamp` can be manipulated by miners within a certain range (up to 900 seconds on Ethereum). This could allow a miner to slightly accelerate or delay vesting withdrawals, though the impact on long-term vesting schedules is typically minor.
IssueThe `withdrawTokenToFounders` and `withdrawTokensToAdvisors` functions use `now` (an alias for `block.timestamp`) to determine if vesting periods have passed. While common, `block.timestamp` can be manipulated by miners within a certain range (up to 900 seconds on Ethereum). This could allow a miner to slightly accelerate or delay vesting withdrawals, though the impact on long-term vesting schedules is typically minor.
FixFor critical time-sensitive operations, consider using an oracle for time if precise, unmanipulable time is required. For vesting schedules, `block.timestamp` is generally acceptable given the long durations, but users should be aware of this minor manipulation potential.
StatusUnresolved
Low

Outdated Solidity Compiler Version

L-01The contract is compiled with `pragma solidity ^0.4.18`. This version is significantly outdated. Newer Solidity versions (e.g., 0.8.x) include numerous security enhancements, bug fixes, and gas optimizations. Using an older compiler version may expose the contract to known compiler-related vulnerabilities or lead to less efficient code.
IssueThe contract is compiled with `pragma solidity ^0.4.18`. This version is significantly outdated. Newer Solidity versions (e.g., 0.8.x) include numerous security enhancements, bug fixes, and gas optimizations. Using an older compiler version may expose the contract to known compiler-related vulnerabilities or lead to less efficient code.
FixConsider migrating the contract to a modern Solidity compiler version (e.g., 0.8.x). This would require thorough re-auditing and testing due to breaking changes between versions, but would significantly improve the contract's security posture and efficiency.
StatusUnresolved
Low

Redundant `Transfer` Event Declaration

L-02The `TracToken` contract re-declares the `Transfer` event (`event Transfer(address indexed from, address indexed to, uint256 value);`) which is already declared in `ERC20Basic`. While not a functional vulnerability, this is redundant and can lead to minor confusion or slight gas inefficiency if the compiler processes it multiple times.
IssueThe `TracToken` contract re-declares the `Transfer` event (`event Transfer(address indexed from, address indexed to, uint256 value);`) which is already declared in `ERC20Basic`. While not a functional vulnerability, this is redundant and can lead to minor confusion or slight gas inefficiency if the compiler processes it multiple times.
FixRemove the redundant `Transfer` event declaration from the `TracToken` contract. The event declared in `ERC20Basic` is sufficient and will be inherited and emitted correctly.
StatusUnresolved
Info

`SafeMath.div` Lacks Division-by-Zero Check

I-01The `SafeMath.div` function is implemented as `uint256 c = a / b; return c;`. It does not explicitly check if the divisor `b` is zero before performing the division. While Solidity's built-in division operation would revert on division by zero, an explicit `require(b != 0)` check is a best practice for clarity and consistency in a SafeMath library.
IssueThe `SafeMath.div` function is implemented as `uint256 c = a / b; return c;`. It does not explicitly check if the divisor `b` is zero before performing the division. While Solidity's built-in division operation would revert on division by zero, an explicit `require(b != 0)` check is a best practice for clarity and consistency in a SafeMath library.
FixAdd a `require(b != 0, "SafeMath: division by zero")` check at the beginning of the `div` function in the `SafeMath` library.
StatusUnresolved
Info

`approve` Function's Anti-Race Condition Assertion

I-02The `approve` function in `StandardToken` includes an assertion: `assert(allowed[msg.sender][_spender] == 0 || _value == 0);`. This assertion prevents the known ERC20 `approve` race condition where a user might approve a new amount before the spender has spent the old amount, potentially allowing the spender to spend both amounts. This is a positive security measure, although it forces users to set allowance to 0 first before increasing it, which can be inconvenient. The `increaseApproval` and `decreaseApproval` functions are provided as safer alternatives.
IssueThe `approve` function in `StandardToken` includes an assertion: `assert(allowed[msg.sender][_spender] == 0 || _value == 0);`. This assertion prevents the known ERC20 `approve` race condition where a user might approve a new amount before the spender has spent the old amount, potentially allowing the spender to spend both amounts. This is a positive security measure, although it forces users to set allowance to 0 first before increasing it, which can be inconvenient. The `increaseApproval` and `decreaseApproval` functions are provided as safer alternatives.
FixNo direct recommendation for change, as this is a deliberate security choice. Users should be educated to use `increaseApproval` and `decreaseApproval` for modifying allowances to avoid the `approve` race condition and the inconvenience of setting allowance to zero first.
StatusUnresolved

Category Ratings

TechnicalMedium5/10

The contract utilizes the SafeMath library, which is a strong practice for preventing integer overflows/underflows (7.2 Code Security). However, the `SafeMath.div` function lacks a division-by-zero check, which is a minor flaw in the library itself. The contract is compiled with Solidity ^0.4.18, an outdated version, which may expose it to known compiler bugs and lacks modern security features and gas optimizations (7.2 Code Security). The `approve` function includes an assertion to mitigate the known ERC20 race condition, which is a positive security measure (7.2 Code Security).

GovernanceHigh1/10

The contract exhibits high centralization, with the `owner` having extensive control over token minting, transferability, and allocation (7.3 Access Control). A critical economic vulnerability allows the owner to mint tokens beyond the declared `TOTAL_NUM_TOKENS` limit, leading to potential hyperinflation and devaluation (7.4 Economic). Vesting functions for founders and advisors are dependent on the `mintingFinished` flag, meaning tokens cannot be withdrawn until the owner enables transfers, which could lead to delays (7.4 Economic). The vesting schedules also rely on `block.timestamp`, which is susceptible to minor miner manipulation (7.4 Economic).

UpgradesHigh2/10

The TracToken contract is not designed with upgradeability in mind (7.1 Architecture). It does not implement any proxy patterns (e.g., UUPS, Transparent) or other mechanisms for future upgrades. Therefore, there are no specific upgrade-related risks or benefits to assess (7.7 Upgrades). Any changes to the contract logic would require a new deployment and migration of assets.

Security Checklist

Contract VerifiedPass
Ownership RenouncedFail
No Mint FunctionFail
Liquidity LockedFail
Not a ProxyPass

Holder Composition

26.9% in wallets24.4% in contracts
Effective Concentration36.7%

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 Holder51.5%
Top-3 Unlocked86.0%

Key Addresses

Deployer
0xe80d…471a
Unlocked LP Held By
0xb774…d7ab0x8237…1b720xa641…3e380xe019…d1a70x09f3…e528

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

What Raised This Score

  • Ownership NOT renounced — owner is an EOA (single private key)
  • Mintable supply — no cap found, dilution unbounded
  • Top-10 concentration > 30% (51.3% total → 36.7% effective; 26.9% in EOAs, 24.4% in contracts — moderate)
  • Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
  • LP top1 unlocked holder = 51.5% (independent LP — depth risk, pool = 72% of DEX liquidity)
  • LP top3 unlocked holders = 86.0% (independent LP — depth risk, pool = 72% of DEX liquidity)
  • 1 Critical finding(s) from audit
  • 1 High finding(s) from audit
  • 2 Medium finding(s) from audit
  • 2 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

DIAToken (DIA)High RiskTERAFABHigh RiskStargate Finance (STG)High RiskREHigh RiskZamaHigh RiskUNICURVEHigh Risk

Would You Like a More Detailed Audit of Trace Token?

Our AI-powered scanner gives you a deeper, real-time smart contract analysis — free, with every scoring factor shown.

Get Detailed Audit