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.

On-chain security analysis — is it a scam or legit?
Is Trace 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 TracToken contract is an ERC-20 compliant token with minting and vesting functionalities.
Read the full analysis- Ownership not renounced — owner is an EOA
- 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 = 51.5%
- LP top3 unlocked holders = 86.0%
- 1 Critical finding(s) from audit
- 1 High finding(s) from audit
- 2 Medium finding(s) from audit
- 2 Low finding(s) from audit
Exact factors
- 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
Security Checklist
as of audit · Sep 4Holders
as of audit · Sep 4, 2026- Contractstreasury, vesting, bridge, staking24.4%
- Walletsanonymous holders, free to sell26.9%
- Everyone elsethe rest of the supply48.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 4The 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.
0xb774…d7ab0x8237…1b720xa641…3e380xe019…d1a70x09f3…e528No privileged address appears among these holders: the unlocked liquidity sits with independent providers, not with the deployer.
Security Findings
CriticalOwner Can Mint Tokens Beyond TOTAL_NUM_TOKENS Limit
The 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.C-01
TOTAL_NUM_TOKENS LimitIssue
The 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.
Fix
Implement 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.
Status
Unresolved
HighHigh Centralization of Control
The 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.H-01
Issue
The 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.
Fix
Consider 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.
Status
Unresolved
MediumVesting Functions Dependent on mintingFinished Flag
The 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.M-01
mintingFinished FlagIssue
The 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.
Fix
Re-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.
Status
Unresolved
MediumUse of block.timestamp for Vesting Schedules
The 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.M-02
block.timestamp for Vesting SchedulesIssue
The 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.
Fix
For 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.
Status
Unresolved
LowOutdated Solidity Compiler Version
The 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.L-01
Issue
The 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.
Fix
Consider 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.
Status
Unresolved
LowRedundant Transfer Event Declaration
The 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.L-02
Transfer Event DeclarationIssue
The 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.
Fix
Remove the redundant Transfer event declaration from the TracToken contract. The event declared in ERC20Basic is sufficient and will be inherited and emitted correctly.
Status
Unresolved
InfoSafeMath.div Lacks Division-by-Zero Check
The 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.I-01
SafeMath.div Lacks Division-by-Zero CheckIssue
The 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.
Fix
Add a require(b != 0, "SafeMath: division by zero") check at the beginning of the div function in the SafeMath library.
Status
Unresolved
Infoapprove Function's Anti-Race Condition Assertion
The 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.I-02
approve Function's Anti-Race Condition AssertionIssue
The 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.
Fix
No 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.
Status
Unresolved
Analysis
AI Copilotas of audit · Sep 4The 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).
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).
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.
It is strongly recommended to address the critical vulnerability allowing unlimited token minting by implementing a hard cap check within the mint function.
Review and reduce the extensive centralization of control by considering multi-signature wallets for critical operations or implementing time-locks where appropriate. Update the contract to a modern Solidity compiler version (e.g., 0.8.x) to benefit from security enhancements and gas optimizations. Evaluate the vesting logic to ensure it aligns with economic expectations, particularly regarding the dependency on the mintingFinished flag.
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, 202667High
- Aug 17, 202669High
Score changes are recorded as dated snapshots — history is append-only and cannot be edited.
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 Is this your token? Publish your own audit on this page