The DopplerERC20V1 contract implements an ERC20 token with vesting schedules and a temporary balance limit feature. The contract utilizes audited Solady libraries, enhancing code quality. However, a significant portion of the core vesting calculation and balance limit enforcement logic was not provided for review, preventing a comprehensive security assessment of these critical features. The initialization process is complex, and the controller role has centralized power over the balance limit.
On-chain security analysis — is it a scam or legit?
Is Free Bots 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 DopplerERC20V1 contract implements an ERC20 token with vesting schedules and a temporary balance limit feature.
Read the full analysis- Ownership not renounced — owner is a contract
- Proxy contract
- Non-standard proxy storage
- Top-10 concentration > 20%
- Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
- LP top1 unlocked holder = 70.0%
- LP top3 unlocked holders = 92.7%
- Token age < 30 days
- 1 High finding(s) from audit
- 1 Medium finding(s) from audit
- 1 Low finding(s) from audit
Exact factors
- Ownership NOT renounced — owner is a contract (governance/executor, not an EOA)
- Proxy contract (upgradeable — admin can replace logic)
- Non-standard proxy storage (Etherscan-confirmed)
- Top-10 concentration > 20% (52.5% total → 25.6% effective; 7.6% in EOAs, 44.9% in contracts — mild)
- Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
- LP top1 unlocked holder = 70.0% (independent LP — depth risk, pool = 99% of DEX liquidity)
- LP top3 unlocked holders = 92.7% (independent LP — depth risk, pool = 99% of DEX liquidity)
- Token age < 30 days (still settling)
- 1 High finding(s) from audit
- 1 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 4Holders
as of audit · Sep 4, 2026- Contractstreasury, vesting, bridge, staking44.9%
- Walletsanonymous holders, free to sell7.6%
- Everyone elsethe rest of the supply47.5%
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 4- Uniswap v4WETHAnalysed$165.9K99.4%
- Uniswap v4USDC$7530.5%
- Uniswap v4USDC$1600.1%
- Uniswap v4USDC$280.0%
- Uniswap v4USDC$20.0%
- Uniswap v4ETH$10.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.
0x0b23…1b140x48eb…74340x1983…a2580xbc78…f26d0x85f9…ea620x6b91…a23d0x72b5…5a230x05c8…7f870x5ea2…99020x335e…b2dfNo privileged address appears among these holders: the unlocked liquidity sits with independent providers, not with the deployer.
Security Findings
HighIncomplete Vesting and Balance Limit Enforcement Logic
The provided source code is truncated, specifically missing the implementation of the _available function, which is crucial for calculating releasable vested amounts. Furthermore, the actual enforcement logic for the maxBalanceLimit within token transfers (e.g., in _beforeTokenTransfer or a custom _transfer override) is not present. This prevents a comprehensive security assessment of two core functionalities of the token.H-01
Issue
The provided source code is truncated, specifically missing the implementation of the _available function, which is crucial for calculating releasable vested amounts. Furthermore, the actual enforcement logic for the maxBalanceLimit within token transfers (e.g., in _beforeTokenTransfer or a custom _transfer override) is not present. This prevents a comprehensive security assessment of two core functionalities of the token.
Fix
Provide the complete and untruncated source code, including the full implementation of the _available function and any logic responsible for enforcing the maxBalanceLimit during token transfers.
Status
Unresolved
MediumCentralized Control over Balance Limit Disablement
The controller address, set during initialization and immutable, possesses the sole authority to disable the isBalanceLimitActive feature via the disableBalanceLimit() function. A compromise of this single key could lead to the balance limit being removed prematurely, potentially impacting token distribution or market stability if the limit is a critical economic safeguard.M-01
Issue
The controller address, set during initialization and immutable, possesses the sole authority to disable the isBalanceLimitActive feature via the disableBalanceLimit() function. A compromise of this single key could lead to the balance limit being removed prematurely, potentially impacting token distribution or market stability if the limit is a critical economic safeguard.
Fix
Consider implementing a multi-signature wallet for the controller role to distribute control, or introduce a time-locked mechanism for disabling the balance limit to provide a delay for community intervention. If a single EOA is intended, ensure robust key management practices are in place.
Status
Unresolved
LowComplex Initialization Function
The initialize function is highly complex, accepting numerous parameters including multiple arrays for vesting schedules and beneficiary allocations, along with conditional setup for the balance limit. While checks are in place (e.g., ArrayLengthsMismatch, InvalidSchedule), the high number of inputs and intricate logic increases the risk of human error during deployment, potentially leading to misconfiguration or unintended behavior.L-01
Issue
The initialize function is highly complex, accepting numerous parameters including multiple arrays for vesting schedules and beneficiary allocations, along with conditional setup for the balance limit. While checks are in place (e.g., ArrayLengthsMismatch, InvalidSchedule), the high number of inputs and intricate logic increases the risk of human error during deployment, potentially leading to misconfiguration or unintended behavior.
Fix
Thoroughly review and test all deployment scripts and parameters. Consider implementing robust off-chain tooling to generate and validate initialization parameters. For future versions, evaluate if some complex setup steps could be broken down into smaller, more auditable post-initialization functions if feasible.
Status
Unresolved
InfoImmutability of Controller Address
The controller address, which is responsible for disabling the balance limit, is set during the initialize function and cannot be changed thereafter. While this prevents malicious reassignments, it also means that if the controller's private key is lost or compromised, the role cannot be recovered or transferred without a full contract redeployment or upgrade (if deployed as a proxy).I-01
Issue
The controller address, which is responsible for disabling the balance limit, is set during the initialize function and cannot be changed thereafter. While this prevents malicious reassignments, it also means that if the controller's private key is lost or compromised, the role cannot be recovered or transferred without a full contract redeployment or upgrade (if deployed as a proxy).
Fix
Acknowledge the implications of an immutable controller. If long-term flexibility or recovery mechanisms are desired, consider adding an onlyOwner function to update the controller address in future iterations, potentially with a timelock.
Status
Unresolved
InfoUse of Initializable in Non-Proxy Context
The contract inherits Initializable and calls _disableInitializers() in its constructor, which is a standard pattern for upgradeable contracts deployed behind a proxy. However, the provided metadata indicates that is_proxy: false, suggesting it is deployed as a standalone contract. While this setup is safe (prevents re-initialization), it implies the contract was either designed for upgradeability but deployed directly, or the metadata is incorrect.I-02
Issue
The contract inherits Initializable and calls _disableInitializers() in its constructor, which is a standard pattern for upgradeable contracts deployed behind a proxy. However, the provided metadata indicates that is_proxy: false, suggesting it is deployed as a standalone contract. While this setup is safe (prevents re-initialization), it implies the contract was either designed for upgradeability but deployed directly, or the metadata is incorrect.
Fix
Clarify the intended deployment strategy. If upgradeability is desired, ensure the contract is deployed behind a proxy. If not, the Initializable pattern is benign but adds unnecessary complexity and might cause confusion regarding the contract's upgradeability status.
Status
Unresolved
Analysis
AI Copilotas of audit · Sep 4The contract leverages robust Solady libraries for ERC20, Ownable, and Initializable functionalities, contributing to a solid architectural foundation (7.1). Access control (7.3) is implemented using Ownable and a onlyController modifier, which is standard. However, the absence of the _available function's implementation and the actual balance limit enforcement logic (7.2) prevents a full assessment of the token's core security mechanisms. The initialize function's complexity (7.2) also introduces potential for misconfiguration.
The contract defines economic parameters such as MAX_PRE_MINT_PER_ADDRESS_WAD and MAX_TOTAL_PRE_MINT_WAD which are enforced during initialization (7.4). The owner has control over locking/unlocking the pool and updating the token URI. A controller role, set immutably, holds the power to disable the balance limit (7.5). This centralized control over a key economic parameter introduces a single point of failure if the controller's key is compromised.
The contract includes Initializable and _disableInitializers() in its constructor, indicating a design for upgradeability (7.7). However, the provided metadata states is_proxy: false, suggesting it's deployed as a standalone contract. This setup is safe but means the contract is not upgradeable in its current deployment, which might be a discrepancy between design and deployment strategy.
It is critical to provide the complete source code, especially the _available function and any token transfer overrides, to enable a full security assessment of the vesting and balance limit mechanisms.
For the controller role, consider implementing a multi-signature wallet or a time-locked mechanism to mitigate the risk of centralized control over the balance limit disablement. Ensure thorough testing of the complex initialize function parameters to prevent misconfiguration during deployment.
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, 202660Medium
- Aug 30, 202661Medium
Score changes are recorded as dated snapshots — history is append-only and cannot be edited.
Would You Like a More Detailed Audit of Free Bots?
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