TrustNet Score
The TrustNet Score evaluates crypto projects based on audit results, security, KYC verification, and social media presence. This score offers a quick, transparent view of a project's credibility, helping users make informed decisions in the Web3 space.
Real-Time Threat Detection
Real-time threat detection, powered by Cyvers.io,
is currently not
activated
for this project.
This advanced feature provides continuous monitoring and instant alerts to safeguard your assets from potential security threats. Real-time detection enhances your project's security by proactively identifying and mitigating risks.
For more information, click here.
Summary and Final Words
No crucial issues found
The contract does not contain issues of high or medium criticality. This means that no known vulnerabilities were found in the source code.
Contract owner cannot mint
It is not possible to mint new tokens.
Contract owner cannot blacklist addresses.
It is not possible to lock user funds by blacklisting addresses.
Contract owner cannot set high fees
The fees, if applicable, can be a maximum of 25% or lower. The contract can therefore not be locked. Please take a look in the comment section for more details.
Token transfer can be locked
Owner can lock user funds with owner functions.
Token cannot be burned
There is no burning within the contract without any allowances
Ownership is not renounced
The owner retains significant control, which could potentially be used to modify key contract parameters.
Contract is not upgradeable
The contract does not use proxy patterns or other mechanisms to allow future upgrades. Its behavior is locked in its current state.
Scope of Work
This audit encompasses the evaluation of the files listed below, each verified with a SHA-1 Hash. The team referenced above has provided the necessary files for assessment.
The auditing process consists of the following systematic steps:
- Specification Review: Analyze the provided specifications, source code, and instructions to fully understand the smart contract's size, scope, and functionality.
- Manual Code Examination: Conduct a thorough line-by-line review of the source code to identify potential vulnerabilities and areas for improvement.
- Specification Alignment: Ensure that the code accurately implements the provided specifications and intended functionalities.
- Test Coverage Assessment: Evaluate the extent and effectiveness of test cases in covering the codebase, identifying any gaps in testing.
- Symbolic Execution: Analyze the smart contract to determine how various inputs affect execution paths, identifying potential edge cases and vulnerabilities.
- Best Practices Evaluation: Assess the smart contracts against established industry and academic best practices to enhance efficiency, maintainability, and security.
- Actionable Recommendations: Provide detailed, specific, and actionable steps to secure and optimize the smart contracts.
A file with a different Hash has been intentionally or otherwise modified after the security review. A different Hash may indicate a changed condition or potential vulnerability that was not within the scope of this review.
Final Words
The following provides a concise summary of the audit report, accompanied by insightful comments from the auditor. This overview captures the key findings and observations, offering valuable context and clarity.
Smart Contract Analysis Statement
Contract Analysis
The Clash contract implements an ERC20 token with a configurable set of launch controls: adjustable buy, sell and transfer fees with an optional burn share, maximum wallet and maximum transaction limits, a trade cooldown, a blacklist, an optional whitelist, an anti-dump limiter, dead-block anti-sniping, batch transfers, a pause switch, optional minting and burning, gasless approvals through permit, and an owner token and ETH rescue. It is deployed as an immutable minimal-proxy clone that delegates to a single shared implementation, so the token is initialized once at creation and is not upgradeable afterwards.
Ownership Privileges
The ownership of the contract has been retained by a single externally owned account, which is not a multisig and is not behind a timelock; on the live token the owner has additionally blocked further ownership transfers and frozen several modules. The owner retains full privileges including:
- Deciding when trading opens, and thereby permitting or withholding transfers for all non-exempt holders.
- Setting the buy, sell and transfer fees up to the ceiling fixed at deployment and choosing the address that receives the fee.
- Adding or removing addresses on the blacklist and on the fee, limit, cooldown and anti-dump exemption lists, and designating market-maker pairs.
- Rescuing tokens or ETH held by the contract, and configuring the cooldown, limits and anti-dump parameters while those modules remain unfrozen.
- Cannot set any fee above the ceiling fixed at deployment, which is at most twenty percent and is five percent on the live token, so the fee can never reach twenty-five percent.
- Cannot re-enable a feature that was disabled at deployment; on the live token minting is disabled and cannot be turned back on.
- Cannot change the values of a module once that module has been frozen, and on the live token the fees, limits and blacklist are already frozen and the name is locked.
- Cannot mint or move tokens away from holders without their keys; balances can be frozen through the blacklist but cannot be silently taken.
Security Features
The contract implements several positive security features:
- The shared implementation disables initializers, so it cannot be taken over directly, and each token is an immutable clone with no upgrade path or admin proxy.
- Fees are hard-capped at deployment and value is conserved on every transfer, so what leaves a sender always equals what the receiver, the fee recipient and the burn address together receive; this was confirmed with property and invariant testing.
- Permanent freeze switches lock the fee rates, limit thresholds, cooldown and anti-dump parameters, and the blacklist, and disabled modules can never be re-enabled. One caveat worth noting is that the per-address exemption lists remain adjustable after a freeze unless they are separately locked.
- The token builds on well-reviewed standard libraries for the token core, ownership, permit and safe transfers, uses only checked arithmetic, and has no external price feeds, no reflection or auto-liquidity swaps, and no callback hooks that would create a reentrancy surface.
Current On-chain Configuration
At the time of review the live token had trading not yet enabled, which means only the owner and exempt addresses could move tokens; minting was disabled; the token was not pausable; the buy fee was two percent and the sell fee five percent with twenty percent of the fee burned; the maximum-wallet limit was set and frozen; and the blacklist, fees and limits were frozen while the cooldown and anti-dump modules remained changeable. Holders should understand that opening trading rests entirely with the owner.
Note - This Audit report consists of a security analysis of the Clash smart contract. This analysis did not include economic analysis of the contract's tokenomics. Moreover, we only audited the main contract for the Clash team. Other contracts associated with the project, including the factory that creates and initializes the token clones, were not audited by our team. We recommend investors do their own research before investing.
Files and details
Findings and Audit result
medium Issues | 3 findings
Pending
#1 medium Issue
Pause can be bypassed through the batch transfer skip-fee path
The pause check lives in a modifier on the overridden update function. The batch transfer fee-skip path calls the parent update function directly through an internal helper, so it never runs that modifier. When the fee-skip mode applies to the caller, transfers still succeed while the token is paused, which defeats the emergency stop. Depending on the batch access configuration this path can be reachable by any user, not only the owner.
Pending
#2 medium Issue
Broad administrative powers held by a single key with no timelock
A single externally owned account holds every administrative power in the contract, including fee changes up to the configured ceiling, address exemptions, market-maker designation, fund rescue, and minting where it is enabled. There is no timelock, and ownership is transferred in a single step. A lost or compromised key would let an attacker retune fees, exempt themselves, or otherwise disrupt the token in one transaction with no delay for holders to react. On the reviewed deployment the owner is a plain externally owned account and several modules have already been frozen, which reduces but does not remove the concern.
Pending
#3 medium Issue
Owner can withhold trading indefinitely and lock non-exempt holders
Transfers are gated by a trading switch that only the owner can turn on. While trading is off, a transfer reverts only when both parties are non-exempt; a transfer to or from any exempt address, such as the owner, an exempted account, or a designated market-maker pair, still goes through. The owner can therefore keep ordinary holders from moving tokens for as long as no exempt exit path exists, and there is no time bound or fallback that forces trading to open. The impact is conditional on whether such an exit path is ever opened. For the reviewed token it was confirmed on-chain that trading was never enabled, no decentralized exchange pair had been created or designated, and most of the supply had already been distributed to holders, so non-exempt holders currently have no way to sell or move their tokens. This is the classic honeypot setup and rests entirely on owner discretion.
low Issues | 10 findings
Pending
#1 low Issue
Batch transfers can skip fees for ordinary users
When batch transfers are configured to skip fees for the caller, the batch path moves tokens without applying the buy, sell, or transfer fee. If the batch function is also open to the public, any holder can avoid the fee by sending through a single-recipient batch instead of a normal transfer. On the reviewed live deployment the batch function is owner-only and only the owner skips fees, so it is not exploitable there, but the contract allows a configuration where the public can bypass fees.
Pending
#2 low Issue
Fee can be silently retained by the sender under a specific fee setting
The fee split only burns a portion when burning is enabled. If fees are turned on with a full burn share while burning is disabled and the fee recipient is the zero address, the fee is neither burned nor collected. It simply stays with the sender while the receiver gets less than the sent amount. The outcome is a silent shortfall to the receiver and an uncollected fee. The setter permits this combination because a full burn share is allowed to have a zero recipient.
Pending
#3 low Issue
Renounce is not covered by the ownership transfer block
Blocking ownership transfer prevents handing ownership to a new address, but the standard renounce function is not covered by the same guard. After ownership transfer has been blocked, the owner can still renounce and set the owner to the zero address. That permanently disables every administrative function and freezes the current configuration, which is a very different outcome from what the block appears to promise.
Pending
#4 low Issue
Permit signing domain becomes stale after a name change
The signing domain used for permit is fixed to the name provided at initialization, while the token name can later be changed through the metadata setter. After a rename, the value returned by the name getter no longer matches the permit signing domain. Wallets and tools that build the domain from the current name will then produce signatures that fail to validate. On the live deployment the metadata is locked, so it does not occur there, but a token that keeps metadata mutable is exposed.
Pending
#5 low Issue
Missing zero check on router and stale exemptions when a pair is removed
The router address can be set to the zero address with no validation. Separately, turning off a market-maker pair sets the pair flag to false but leaves the fee, limit, cooldown, and anti-dump exemptions that were granted when the pair was added. A former pair address therefore keeps bypassing limits and fees even though it is no longer treated as a pair.
Pending
#6 low Issue
Mode selectors are not range-checked at initialization
Several mode selectors are stored as small integers without range checks, including the whitelist mode, the anti-dump type, the dead-block mode, and the batch access and fee modes. Out-of-range values silently change behavior. For example, an unexpected batch access value leaves the batch function open to the public, and an unexpected dead-block mode disables the protection the deployer intended to enable.
Pending
#7 low Issue
Freeze controls do not lock the exemption maps
The freeze functions for fees, limits, cooldown, and anti-dump only lock the rate and threshold setters. They do not lock the per-address exemption maps, and designating a market-maker pair still grants that pair every exemption. After a module is frozen, the owner can still change who is subject to it by toggling exemptions or by adding a new pair. The global rates and limits stay fixed, so the residual power can only relax the rules for chosen addresses or place a previously exempt address back under them, but it undercuts the immutability that a freeze appears to promise. The blacklist freeze does not have this gap because there is no blacklist exemption map.
Pending
#8 low Issue
Router protection does not block router-mediated swaps
The pre-trading router protection reverts only when the sender or the recipient of a token transfer equals the configured router address. In a standard exchange swap the router is the caller that moves tokens between the user and the pair, so it is never itself the sender or recipient of the token transfer. The check therefore does not stop swaps routed through that router; it only catches direct transfers to or from the router address. On the live token the router is unset, so the control is inert, and the real pre-trading control is the exempt-counterparty gate rather than this check.
Pending
#9 low Issue
Batch skip-fee path can burn to the zero address and bypass the burn switch
The batch skip-fee path moves tokens by calling the low-level update directly, which skips the zero-recipient check that the normal transfer path enforces. A caller can pass the zero address as a recipient and burn their own tokens through the batch function, even when burning has been disabled for the token. The tokens burned are the caller's own, so there is no direct loss to others, but it breaks the guarantee that burning is off and the expectation that a plain transfer never reduces total supply. It is reachable by the public only when batch fee-skipping is open to non-owners, and it shares its root cause with the pause bypass.
Pending
#10 low Issue
Owner can freeze arbitrary holder balances through the blacklist
The owner can add any address to a blacklist that blocks it from sending or receiving tokens. Blacklisted balances are not slashed, but the funds become non-transferable for as long as the entry stands, which is a strong control over user funds. On the live deployment the blacklist has been frozen, so no new addresses can be added, but any entries made before the freeze remain in effect.
optimization Issues | 4 findings
Pending
#1 optimization Issue
Cache storage reads inside batch and whitelist loops
The batch transfer and whitelist batch loops read storage values on every iteration, including the maximum batch size and repeated mapping and owner lookups. Caching the values that do not change during the loop into memory before it runs reduces gas, and the saving grows with the size of the batch.
Pending
#2 optimization Issue
Replace repeated numeric literals with named constants
The basis-point denominator and the fee ceiling appear as bare numeric literals in several places. Declaring them as named constants makes the intent clear and avoids scattering the same values across the code.
Pending
#3 optimization Issue
Pause modifier is used only once
The pause modifier is applied to a single function. Inlining the check or wrapping its body in an internal function can slightly reduce the deployed code size without changing behavior.
Pending
#4 optimization Issue
Upgradeable reentrancy guard would avoid an extra storage write
Because the non-upgradeable reentrancy guard is not primed by a constructor in a clone, the first guarded call performs an extra cold storage write as the slot moves from its zero value. The upgradeable guard sets the slot during initialization and avoids that one-time cost.
informational Issues | 12 findings
Pending
#1 informational Issue
Floating compiler pragma
The pragma is a floating range rather than a fixed version. The deployed code was compiled with one specific compiler version, and pinning the source to that version avoids accidental drift and the risk of compiling with a version that carries known bugs.
Pending
#2 informational Issue
State changes without events
Several state-changing setters do not emit events, including the fee, limit, and cooldown exemption setters and the two rescue functions. Without events, indexers and monitoring tools cannot reliably observe when these changes happen.
Pending
#3 informational Issue
Event address parameters are not indexed
Several events carry address parameters that are not indexed. Indexing those parameters makes it easier for indexers and dashboards to filter events by address.
Pending
#4 informational Issue
Naming, magic numbers, and function complexity
Minor code-quality items are present. One function name does not follow the usual mixed-case convention, several magic numbers are repeated, and the main pre-transfer routine has high branching complexity that makes it harder to read and maintain.
Pending
#5 informational Issue
Incomplete documentation on public interface
Most external and public functions lack documentation comments describing their parameters, behavior, and access control. Complete documentation helps both reviewers and integrators understand the intended use of each function.
Pending
#6 informational Issue
Standard approval race condition
The token uses the standard approval model, which carries the well known allowance ordering issue where a spender can use both the old and the new allowance if a change is not sequenced carefully. The token does expose permit, which offers a safer approval flow.
Pending
#7 informational Issue
Reentrancy guard is not the first modifier
On the ETH rescue function the reentrancy guard is not the first modifier. In this contract the access-control modifier that runs before it makes no external call, so the ordering is harmless, but placing the guard first is the safer convention.
Pending
#8 informational Issue
Duplicate storage for name and symbol
The token keeps its own copy of the name and symbol in addition to the values held by the base token contract, and overrides the getters to return the custom copies. This duplicates storage and can cause the two sources to diverge after a metadata change, which also underlies the permit domain issue noted separately.
Pending
#9 informational Issue
Decimals value is not bounded
The number of decimals is taken directly from configuration with no upper bound. An unusually large value would not threaten funds but could break display and arithmetic for wallets and integrators that assume a normal range.
Pending
#10 informational Issue
Non-upgradeable reentrancy guard mixed into a clone-based contract
The contract inherits the non-upgradeable reentrancy guard, which keeps its status in a regular storage slot, while the rest of the contract uses the namespaced storage of the upgradeable base contracts. For the immutable clone deployment this works correctly and has no security impact, so it is treated as informational. The constructor that primes the guard does not run for clones, so the first guarded call pays a small extra gas cost, and the fixed slot would only be unsafe if the code were later placed behind a true upgradeable proxy alongside other sequential storage.
Pending
#11 informational Issue
Clone initialization safety depends on the deploying factory
The implementation correctly disables initializers in its constructor, so it cannot be initialized directly. Each clone still has to be initialized after it is created. If the deploying factory does not create and initialize a clone in the same transaction, an attacker could initialize a freshly created clone first and take ownership and the initial supply. The factory contract was not part of this review, so this is recorded as a dependency to confirm rather than a confirmed weakness in the audited code.
Pending
#12 informational Issue
Permit can be permanently disabled with no way to re-enable it
Permit is controlled by a flag that is only set at initialization and has no setter afterwards. A token deployed with permit disabled will reject permit calls forever, which can break integrations that rely on gasless approvals. This is a product and configuration choice rather than a fault, but it is easy to overlook and cannot be reversed once set.