The DERC20 token contract implements ERC20, ERC20Votes, ERC20Permit, and Ownable functionalities, featuring a vesting mechanism and an inflation-based minting system. While the contract utilizes OpenZeppelin libraries for standard token operations and access control, several critical and medium-severity issues were identified, primarily related to the inflation minting mechanism's gas consumption and potential for arithmetic errors, as well as a division-by-zero vulnerability in the vesting calculation. The owner, a 3/6 multisig, holds significant control over key parameters.
On-chain security analysis — is it a scam or legit?
Is Basemate 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 DERC20 token contract implements ERC20, ERC20Votes, ERC20Permit, and Ownable functionalities, featuring a vesting mechanism and an inflation-based minting system.
Read the full analysis- Ownership not renounced — owner is a contract
- Top-10 concentration > 20%
- Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
- LP top1 unlocked holder = 100.0%
- LP top3 unlocked holders = 100.0%
- 1 High finding(s) from audit
- 2 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)
- Top-10 concentration > 20% (56.9% total → 25.9% effective; 5.2% in EOAs, 51.7% in contracts — mild)
- 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)
- LP top3 unlocked holders = 100.0% (independent LP — depth risk)
- 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
Security Checklist
as of audit · Sep 4Holders
as of audit · Sep 4, 2026- Contractstreasury, vesting, bridge, staking51.7%
- Walletsanonymous holders, free to sell5.2%
- Everyone elsethe rest of the supply43.1%
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.
0x0d68…3b7b0xa204…07c1No privileged address appears among these holders: the unlocked liquidity sits with independent providers, not with the deployer.
Security Findings
HighDenial of Service in mintInflation due to Unbounded Loop
The mintInflation function contains a while loop that iterates for each full year passed since currentYearStart_. If block.timestamp is significantly far in the future (e.g., many years), this loop could execute a large number of times, potentially exceeding the block's gas limit. This would prevent the mintInflation function from ever being successfully called, effectively halting the token's inflation mechanism and impacting the protocol's economic model (7.2 Code Security, 7.8 Operations).H-01
mintInflation due to Unbounded LoopIssue
The mintInflation function contains a while loop that iterates for each full year passed since currentYearStart_. If block.timestamp is significantly far in the future (e.g., many years), this loop could execute a large number of times, potentially exceeding the block's gas limit. This would prevent the mintInflation function from ever being successfully called, effectively halting the token's inflation mechanism and impacting the protocol's economic model (7.2 Code Security, 7.8 Operations).
Fix
Refactor the mintInflation function to calculate the total mintable amount over multiple years in a single, constant-time operation, rather than iterating year by year. Alternatively, implement a mechanism to limit the number of years processed per call, requiring multiple transactions for large time gaps.
Status
Unresolved
MediumDivision by Zero Vulnerability in Vesting Calculation
The computeAvailableVestedAmount function calculates vested tokens using `getVestingDataOf[account].totalAmount * (block.timestamp - vestingStart) / vestingDuration. If vestingDuration is initialized to 0` in the constructor, this division will result in a 'division by zero' error when block.timestamp >= vestingStart, causing the release() function to revert for all users (7.2 Code Security). The constructor does not validate vestingDuration_ to be non-zero.M-01
Issue
The computeAvailableVestedAmount function calculates vested tokens using `getVestingDataOf[account].totalAmount * (block.timestamp - vestingStart) / vestingDuration. If vestingDuration is initialized to 0` in the constructor, this division will result in a 'division by zero' error when block.timestamp >= vestingStart, causing the release() function to revert for all users (7.2 Code Security). The constructor does not validate vestingDuration_ to be non-zero.
Fix
Add a `require(vestingDuration_ > 0, "Vesting duration must be greater than zero") check in the constructor to prevent vestingDuration` from being set to zero.
Status
Unresolved
MediumPotential Integer Overflow in mintInflation Calculations
The mintInflation function performs calculations like (supply * yearlyMintRate_ * timeLeftInCurrentYear). While Solidity 0.8+ reverts on overflow by default, if supply becomes extremely large, the intermediate product of these multiplications could exceed type(uint256).max before the final division. This would cause the transaction to revert, preventing further inflation minting and disrupting the token's supply schedule (7.2 Code Security).M-02
mintInflation CalculationsIssue
The mintInflation function performs calculations like (supply * yearlyMintRate_ * timeLeftInCurrentYear). While Solidity 0.8+ reverts on overflow by default, if supply becomes extremely large, the intermediate product of these multiplications could exceed type(uint256).max before the final division. This would cause the transaction to revert, preventing further inflation minting and disrupting the token's supply schedule (7.2 Code Security).
Fix
Consider reordering the multiplication and division operations to minimize the size of intermediate products, or implement checks to ensure intermediate values do not exceed type(uint256).max for very large supply values. For example, (supply / (1 ether * 365 days)) * yearlyMintRate_ * timeLeftInCurrentYear (with careful consideration for precision loss).
Status
Unresolved
LowInaccurate Yearly Calculation for Inflation
The mintInflation function uses 365 days as a constant for a year's duration. This approximation does not account for leap years, which occur every four years and have 366 days. This can lead to minor inaccuracies in the calculated inflation amount over long periods (7.4 Economic).L-01
Issue
The mintInflation function uses 365 days as a constant for a year's duration. This approximation does not account for leap years, which occur every four years and have 366 days. This can lead to minor inaccuracies in the calculated inflation amount over long periods (7.4 Economic).
Fix
While common in smart contracts, for higher precision, consider using a more accurate average year length or a more sophisticated time-tracking mechanism if exact yearly inflation is critical. Acknowledge this as a known precision trade-off.
Status
Unresolved
InfoCentralization of Control by Owner
The contract inherits Ownable, granting the owner address significant control over critical functions such as lockPool, unlockPool, burn, updateMintRate, and updateTokenURI. While the owner is a 3/6 multisig, this still represents a centralized point of control that could be a single point of failure if the multisig signers are compromised or act maliciously (7.3 Access Control, 7.5 Governance).I-01
Issue
The contract inherits Ownable, granting the owner address significant control over critical functions such as lockPool, unlockPool, burn, updateMintRate, and updateTokenURI. While the owner is a 3/6 multisig, this still represents a centralized point of control that could be a single point of failure if the multisig signers are compromised or act maliciously (7.3 Access Control, 7.5 Governance).
Fix
Ensure the multisig wallet holding ownership is secured with robust operational procedures, strong key management, and regular audits. Consider implementing time-locks for sensitive operations to provide a window for community review or emergency intervention.
Status
Unresolved
InfoPERMIT_2 Granted Unlimited Allowance
The allowance function is overridden to return type(uint256).max if the spender is PERMIT_2 (0x0000…8BA3). This grants unlimited spending approval to the PERMIT_2 contract for any user who has approved the DERC20 token for PERMIT_2 (7.2 Code Security, 7.6 External).I-02
PERMIT_2 Granted Unlimited AllowanceIssue
The allowance function is overridden to return type(uint256).max if the spender is PERMIT_2 (). This grants unlimited spending approval to the PERMIT_2 contract for any user who has approved the DERC20 token for PERMIT_2 (7.2 Code Security, 7.6 External).
Fix
This is a common and intentional design pattern for Permit2 integration. Users should be aware that by interacting with Permit2 for this token, they are granting it unlimited spending capabilities. Ensure the PERMIT_2 address is correct and trusted.
Status
Unresolved
InfoMaxTotalVestedExceeded Prevents 100% Initial Supply Vesting
The constructor includes a require(vestedTokens < initialSupply, MaxTotalVestedExceeded(...)) check. This design choice prevents the entire initialSupply from being allocated to vesting. If vestedTokens equals initialSupply, the constructor will revert (7.4 Economic).I-03
MaxTotalVestedExceeded Prevents 100% Initial Supply VestingIssue
The constructor includes a require(vestedTokens < initialSupply, MaxTotalVestedExceeded(...)) check. This design choice prevents the entire initialSupply from being allocated to vesting. If vestedTokens equals initialSupply, the constructor will revert (7.4 Economic).
Fix
This appears to be an intentional design constraint. Document this behavior clearly in project specifications to ensure it aligns with the desired token distribution strategy. If 100% vesting is ever desired, this require statement would need to be adjusted.
Status
Unresolved
Analysis
AI Copilotas of audit · Sep 4The contract leverages well-audited OpenZeppelin libraries for core ERC20 functionality, voting, and access control (7.2 Code Security). The _update override correctly implements a pool lock mechanism (7.1 Architecture). However, the mintInflation function contains an unbounded while loop, posing a denial-of-service risk if a significant amount of time passes between calls (7.8 Operations). Additionally, the inflation calculation is susceptible to integer overflow for extremely large token supplies, and a division-by-zero error can occur in vesting if vestingDuration is zero (7.2 Code Security).
The contract's economic model includes a linear vesting schedule and a yearly inflation mechanism with a capped mint rate (7.4 Economic). The owner (a 3/6 multisig) has significant control, including the ability to lock/unlock the pool, update the mint rate, and burn tokens (7.3 Access Control, 7.5 Governance). While the multisig mitigates single-point-of-failure risks, the identified technical vulnerabilities in mintInflation could disrupt the intended economic model by preventing inflation from being triggered or causing it to revert due to gas limits or overflows (7.4 Economic). The PERMIT_2 address is granted unlimited allowance, which is a design choice requiring trust in the PERMIT_2 contract (7.6 External).
The DERC20 contract is not designed as an upgradeable proxy. Its logic is immutable once deployed. This eliminates upgrade-related risks but means any discovered vulnerabilities or desired feature changes would require a new deployment and migration (7.7 Upgrades).
Prioritize addressing the denial-of-service vulnerability in the mintInflation function by implementing a mechanism to cap the number of years processed per transaction or by using a more gas-efficient calculation.
Implement a check in the constructor to ensure vestingDuration is greater than zero to prevent division-by-zero errors. Review the inflation calculation for potential integer overflows with extremely large token supplies and consider using SafeMath for critical arithmetic operations if not already implicitly handled by Solidity 0.8+. While the owner is a multisig, ensure robust operational procedures are in place for managing the contract's parameters.
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.
- Aug 17, 202648Medium
Score changes are recorded as dated snapshots — history is append-only and cannot be edited.
Would You Like a More Detailed Audit of Basemate?
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