Milestone HODL Token Info
Milestone HODL Token (MHT) is a decentralized protocol on the BNB Smart Chain engineered to transform market growth into direct, automated rewards for holders. By integrating Chainlink Automation technology, MHT eliminates human intervention, ensuring token distribution is strictly based on real-time Market Cap performance.
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.
Security Assessments
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.
Contract cannot be locked
Owner cannot lock any user funds.
Token can be burned
There is a function to burn tokens in 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 Milestone HODL Token (MHT) V4.1 contract implements an ERC20 token with buy/sell taxation on PancakeSwap (2% buy / 5% sell with burn and marketing splits), a milestone-based reward distribution system releasing tokens from a 500M vault when market cap thresholds are reached, a progressive liquidity release mechanism (200M MHT across four tranches), Chainlink Automation for milestone triggering, Chainlink price feed for BNB/USD pricing, and anti-whale transaction limits. The contract underwent a prior audit which identified 3 HIGH, 5 MEDIUM, 5 LOW, 2 OPTIMIZATION, and 5 INFORMATIONAL findings. V4.1 addresses all critical and high-severity findings, with 16 of 18 original findings resolved. During the re-audit, 4 new minor findings were identified (2 LOW, 2 INFORMATIONAL). Details are listed in the findings table below.
Ownership Privileges
The ownership of the contract uses OpenZeppelin's Ownable2Step pattern, requiring the new owner to explicitly accept the transfer. Manual market cap changes are protected by a 24-hour timelock, and milestone executions enforce a 24-hour cooldown between triggers. The owner retains the following privileges:
- Queuing manual market cap updates subject to a 24-hour timelock delay (
queueManualMarketCap,executeManualMarketCap) - Switching between manual and automated market cap modes (
setUseManualMarketCap) - Changing the marketing wallet address, which receives 30% of all milestone distributions plus 1–4% of every taxed trade (
setMarketingWallet) - Setting the PancakeSwap trading pair address with cleanup of old pair exclusions (
setPancakePair) - Excluding or including any address from transaction fees (
excludeFromFees) - Excluding or including any address from the anti-whale transaction limit (
excludeFromMaxTx) - Excluding or including any address from milestone reward eligibility (
excludeFromRewards) - Changing the Chainlink price feed oracle address (
setPriceFeed) - Adjusting
maxTxAmountwithin bounds of 0.1%–10% of total supply (setMaxTxAmount) - Setting the Chainlink Automation registry for
performUpkeepaccess control (setAutomationRegistry) - Releasing initial LP tranche to the liquidity wallet (
enableTrading) - Recovering accidentally sent tokens with tracked balance protection (
rescueTokens) - Sweeping residual locked rewards caused by rounding (
sweepLockedRewards)
Security Features
- OpenZeppelin's
ReentrancyGuardprotectsclaimRewards()against reentrancy attacks Ownable2Steprequires explicit acceptance by the new owner, preventing accidental ownership loss- 24-hour timelock on manual market cap changes provides a monitoring window before values take effect
- 24-hour cooldown between milestone executions prevents rapid vault drainage (minimum 100 days for full vault)
- Constructor validates all critical addresses are not
address(0) - Complete Chainlink price feed validation: round ID, positive price, round completeness, answeredInRound staleness, and 1-hour freshness check
- Automated market cap correctly derives token price from PancakeSwap LP reserves
- Per-side anti-whale enforcement checks the buyer on buys, the seller on sells, and both parties on P2P transfers
- Reward snapshots execute before tax deductions, crediting holders based on full pre-tax balance
- Buy/sell tax percentages are hardcoded and cannot be modified by the owner
- No mint function after deployment — total supply of 1 billion MHT is fixed at construction
- No blacklist mechanism — the owner cannot prevent any address from transferring tokens
- Not upgradeable — no proxy pattern or delegatecall is used
- All admin functions emit events for off-chain monitoring and transparency
rescueTokens()protects tracked balances (vault, rewards, liquidity) from withdrawal
Note — This Audit report consists of a security analysis of the Milestone HODL Token (MHT) V4.1 smart contract. This re-audit verified fixes for 16 of 18 original findings (3 HIGH, 5 MEDIUM, 5 LOW, 2 OPTIMIZATION, 1 INFORMATIONAL) and identified 4 new minor findings (2 LOW, 2 INFORMATIONAL). This analysis did not include economic analysis of the contract's tokenomics. Moreover, we only audited the main contract for the Milestone HODL Token (MHT) team. Other contracts associated with the project were not audited by our team. We recommend investors do their own research before investing.
Files and details
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Findings and Audit result
high Issues | 3 findings
Resolved
#1 high Issue
Broken Automated Market Cap Calculation
getMarketCap() in automated mode computes (circulatingSupply * bnbPriceUSD) / 1e18, which treats each MHT token as worth 1 BNB. With ~500M circulating tokens and BNB at $600, the function returns $300 billion instead of the actual market cap. The function has no access to the MHT/BNB price from PancakeSwap reserves or any token oracle. If useManualMarketCap is set to false, this absurd value exceeds all milestone thresholds, allowing anyone to call performUpkeep() 100 times and drain the entire vault.
Resolved
#2 high Issue
Reward Dilution - Permanently Locked Tokens in RewardsPool
_executeMilestone() calculates milestoneRewardPerToken using _getCirculatingSupply() as the denominator, but this includes tokens held by addresses excluded from rewards (pancakePair, marketingWallet, pinksaleWallet, and any other excluded address). Since excluded addresses can never claim rewards (_updateReward skips them, claimRewards reverts), the reward tokens allocated to their share of circulating supply are permanently locked in rewardsPool. With ~470M tokens in excluded addresses vs ~30M eligible out of ~505M circulating, approximately 94% of each milestone's holder allocation is permanently unclaimable.
Resolved
#3 high Issue
Owner Can Trigger All Milestones Instantly via Manual Market Cap
The owner can call setManualMarketCap() with an arbitrarily high value (e.g., $100M). Since performUpkeep() has no access control (anyone can call it) and no cooldown between executions, all 100 milestones can be triggered in rapid succession within a single block. Each milestone releases 5M tokens (70% to rewardsPool, 30% to marketing wallet), so the entire 500M vault is drained instantly. This is a severe centralization risk: a compromised owner key or a malicious owner can drain the vault and receive 150M tokens to the marketing wallet.
medium Issues | 5 findings
Resolved
#1 medium Issue
Reward Exclusion Toggle Causes Permanent Lock or Unearned Grants
excludeFromRewards() simply flips a boolean without handling pending state. (A) Excluding an address with accrued rewards: pendingRewards mapping retains the value but claimRewards() reverts with 'Excluded from rewards', permanently locking those tokens in rewardsPool. (B) Un-excluding an address: userRewardPerTokenPaid still holds the old snapshot value, so _updateReward calculates a delta that includes all milestones that occurred during exclusion, granting unearned retroactive rewards.
Resolved
#2 medium Issue
Reward Snapshot Timing Issue During Taxed Transfers
In the _update() override, when a taxed sell occurs, the execution order is: (1) tax deducted from sender via super._update (reduces sender balance), (2) _updateReward(sender) snapshots rewards using already-reduced balance, (3) final transfer. The sender loses reward credit on the tax portion. For a 5% sell tax, the user loses 5% of their accrued rewards. This affects every taxed transaction.
Resolved
#3 medium Issue
Anti-Whale maxTxAmount Limit Ineffective for DEX Trades
The anti-whale check requires BOTH from AND to to be non-excluded: !isExcludedFromMaxTx[from] && !isExcludedFromMaxTx[to]. Since setPancakePair() excludes the pair from maxTx, every buy (from=pair) and sell (to=pair) bypasses the limit entirely. A whale can buy or sell unlimited amounts on PancakeSwap. The maxTxAmount only restricts wallet-to-wallet transfers.
Resolved
#4 medium Issue
Incomplete Chainlink Price Feed Validation
getBNBPrice() fetches latestRoundData() but ignores the roundId and answeredInRound return values. Missing validations: answeredInRound >= roundId (ensures answer is from current round, not a stale carryover), updatedAt != 0 (ensures round is complete), roundId != 0 (ensures valid round). Without these, a stale or incomplete oracle response could be accepted as valid.
Resolved
#5 medium Issue
setPancakePair Does Not Clean Up Old Pair Exclusions
When setPancakePair() is called multiple times (e.g., migrating to a new LP pair), the old pair's exclusion flags (isExcludedFromMaxTx, isExcludedFromRewards) are never removed. Old LP pair addresses remain permanently excluded from rewards and maxTx even if they no longer serve as the active trading pair. If the old pair still holds tokens, those tokens inflate the circulating supply denominator, worsening reward dilution.
low Issues | 5 findings
Resolved
#1 low Issue
Divide-Before-Multiply Precision Loss in Milestone Distribution
In _executeMilestone(), forHolders is computed as (MILESTONE_RELEASE * 70) / 100, then used in (forHolders * 1e18) / circulating. Slither correctly flagged this divide-before-multiply pattern. While the current values don't lose precision (5M * 70 is exactly divisible by 100), the accumulated truncation in the second division across 100 milestones causes minor token loss.
Resolved
#2 low Issue
No Setter for maxTxAmount
maxTxAmount is hardcoded at deployment to 10M MHT and has no setter function. If market conditions change and the anti-whale limit needs adjustment, it cannot be modified without a full contract migration. Additionally, since it is only set in the constructor, declaring it as immutable would save ~2100 gas per SLOAD.
Resolved
#3 low Issue
Missing Events for Critical State Changes
Several onlyOwner functions that modify critical contract state do not emit events: setUseManualMarketCap(), setMarketingWallet(), excludeFromFees(), excludeFromMaxTx(), excludeFromRewards(), and setPriceFeed(). Without events, off-chain monitoring tools, indexers, and investors cannot track admin changes, making it harder to detect potentially malicious owner actions.
Resolved
#4 low Issue
No Ownership Transfer Safety (Missing Two-Step Transfer)
The contract uses OpenZeppelin's single-step Ownable pattern. If the owner accidentally transfers ownership to a wrong address (typo, copy-paste error), ownership is irrevocably lost and all admin functions (setManualMarketCap, setPancakePair, setMarketingWallet, etc.) become permanently inaccessible.
Resolved
#5 low Issue
No Token Recovery Mechanism for Accidentally Sent Tokens
If a user accidentally transfers MHT tokens directly to the contract address (not through the reward claim flow), those tokens increase balanceOf(address(this)) but are not tracked by vaultBalance or rewardsPool. They become permanently stuck. Similarly, other ERC-20 tokens or BNB sent to the contract are irrecoverable since there is no rescue/sweep function.
optimization Issues | 2 findings
Resolved
#1 optimization Issue
State Variables Should Be Declared Immutable
pinksaleWallet and maxTxAmount are set only in the constructor and never modified. Declaring them as immutable saves gas on every storage read (~2100 gas per SLOAD) since immutable values are embedded directly in the bytecode rather than read from storage.
Resolved
#2 optimization Issue
Flattened File Contains Unused Interfaces and Dead Code
The flattened source file includes IERC721Errors and IERC1155Errors interfaces (lines 202-308) which are completely unused by this ERC-20 contract. Additionally, Context._contextSuffixLength(), Context._msgData(), and ERC20._burn() are included but never called. This dead code increases deployment cost, bytecode size, and triggers multiple Solidity version pragma warnings (4 different pragma versions in one file).
informational Issues | 5 findings
Resolved
#1 informational Issue
Missing SPDX License Identifier
The source file has no SPDX license identifier, which produces a compiler warning. This is a best practice requirement for open-source Solidity code and is expected for Etherscan/BSCScan verification.
Resolved
#2 informational Issue
Unnamed Return Variable in checkUpkeep
The checkUpkeep() function has an unnamed second return variable 'bytes memory' that always returns empty bytes. While functional, this produces a compiler warning and reduces code clarity.
Resolved
#3 informational Issue
Multiple Solidity Pragma Versions in Flattened File
The flattened file contains 4 different Solidity pragma directives (>=0.4.16, >=0.6.2, >=0.8.4, ^0.8.20). The lower pragma constraints reference Solidity versions with known severe bugs (DirtyBytesArrayToStorage, ABIDecodeTwoDimensionalArrayMemory, etc.). While the actual compilation uses 0.8.20+, this is a cosmetic and tooling concern from the flattening process.
Pending
#4 informational Issue
Zero Test Coverage
The project has zero test coverage for MilestoneHodlToken. No test files exist in the project's test/ directory. For a contract managing 500M+ tokens in a vault with complex reward distribution, buy/sell taxes, and Chainlink integration, this is a critical gap. The PoC tests created during this audit demonstrate that multiple HIGH severity vulnerabilities exist that would have been caught by basic unit tests.
Acknowledged
#5 informational Issue
Naming Convention Violations
Multiple function parameters use underscore prefixes (_usdAmount, _manual, _pair, _wallet, _addr, _status, _feed) which Slither flags as not conforming to Solidity's mixedCase naming convention. While this is a widely used pattern in Solidity, it technically deviates from the style guide.