Mey Network Info
Mey Network is an integrated blockchain ecosystem designed to bridge the gap between physical assets and the digital world. By combining the power of Meychain—a dedicated Layer 1 blockchain for Real-World Assets (RWAs)—and MeyFi, our decentralized nance platform, Mey Network enables seamless tokenization, trading, and management of assets in a secure, scalable environment.
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 can set high fees
Contract owner is able to set fees above 25%. Very high fees can also prevent token transfer.
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 upgradeable
The contract uses a proxy pattern or similar mechanism, enabling future upgrades. This can introduce risks if the upgrade mechanism is not securely managed.
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 PTO contract is a tiered NFT sale and lending pool built on the ERC721 standard, deployed as lightweight clones by a factory that becomes the owner. Buyers fund positions in USDC across time-bounded phases, with eligibility gated by staking tiers or a whitelist signature, and receive pre-minted NFTs immediately while rarity is assigned afterwards through a verifiable randomness flow coordinated by the factory. The contract also supports gifting, where a buyer funds now and a recipient claims later with a signed authorization, and a trading lock that keeps NFTs non-transferable until a configured unlock time.
Ownership Privileges
The ownership of the contract has been assigned to the factory contract, with an additional manager role that shares many day-to-day powers. The owner and managers retain broad privileges including:
- Pre-minting NFTs for sale and configuring pool, phase and rarity parameters before minting begins.
- Withdrawing the raised USDC, the undistributed pre-minted NFTs, and any native balance.
- Rotating the whitelist signer, allowlisting operators for the trading lock, and setting the metadata base URI.
- Moving the withdrawal cursor that controls which pre-minted NFTs can be withdrawn.
- The contract cannot arbitrarily blacklist holders, and it is not an upgradeable-logic proxy, so the deployed logic is fixed.
- Pool and phase economic parameters are frozen once minting starts and cannot be changed mid-sale.
- There is no on-chain timelock and no enforced multisig at the contract level on the privileged actions.
- Because the factory is the owner, the factory's own governance and code determine how these powers are exercised.
Security Features
The contract implements several positive security features:
- All value-moving entry points are protected by a reentrancy guard, and the trading lock is enforced at the transfer chokepoint so it cannot be bypassed by direct transfers.
- Pool and phase parameters are locked once minting begins, removing the risk of mid-sale rule changes.
- Gift claims are authorized by a signature bound to the specific recipient, preventing claim front-running.
- Randomness for rarity is sourced from a verifiable randomness flow rather than on-chain pseudo-randomness, and address setters reject the zero address.
Note - This Audit report consists of a security analysis of the PTO smart contract, a tiered NFT sale and lending pool. This analysis did not include economic analysis of the contract's tokenomics, and the factory contract that owns this contract was not part of the reviewed scope. Moreover, we only audited the main contract for the Mey Network 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
Findings and Audit result
high Issues | 1 findings
Resolved
#1 high Issue
Ineffective trade lock feature due to incomplete implementation
A prior review found that the trade lock only restricted approvals and could be bypassed with direct transfers. The current code enforces the lock inside the transfer update hook, so all transfer paths are covered.
medium Issues | 9 findings
Pending
#1 medium Issue
Unsold phase allocation is rolled over and counted again in multiple later phases
When computing how many NFTs a purchase phase can still sell, the contract adds the unsold remainder of every earlier purchase phase, but a purchase only ever increases the current phase's reserved counter. As a result the leftover from an early phase keeps being added to each subsequent phase even after a middle phase has already absorbed it. A single phase can therefore sell well beyond its own configured cap, and a later phase can advertise more availability than the number of tokens that physically remain. The only hard limit is the global pre-minted supply, so the per-phase caps that shape the intended distribution are not actually enforced. This was reproduced with a test where a phase sold sixty percent over its cap and a following phase reported more remaining than the tokens left.
Pending
#2 medium Issue
Unbounded withdrawal cursor lets a manager seize gift-reserved NFTs
The cursor that the NFT withdrawal uses can be set to any value by a manager or the owner with no bounds. By pointing it into the low range that holds tokens reserved for a pending gift, a privileged account can withdraw those exact tokens to an arbitrary address. The gift recipient can no longer claim, because the assignment transfer reverts once the contract no longer owns the tokens, so the gifted assets are lost. The same lack of bounds can also push the internal accounting out of sync and stall distribution. This was reproduced with a test where a gift's tokens were seized and the recipient's later claim reverted.
Resolved
#3 medium Issue
Rotating the whitelist signer does not revoke the old signer's manager rights
At initialization the whitelist signer is also granted manager rights. The function that rotates the signer only updates the signer address and never removes the previous signer from the manager set. If rotation is performed because the old key may be compromised, that key still holds manager powers such as pre-minting, whitelisting operators and moving the withdrawal cursor, which on its own can break gift custody. The rotation therefore fails to contain the compromise. This was reproduced with a test showing the old signer still executing a manager-only action after rotation.
Acknowledged
#4 medium Issue
Rarity rewards are recorded for the gifter rather than the gift recipient
When a loan is funded as a gift, the address recorded as the minter for the rarity reward is the gifter, because the funding path uses the funder as the minter when requesting randomness. The recipient receives the NFT but the rarity reward rights remain attached to the gifter. Whether this is a defect depends on the intended business rule, but as written the financial reward and the asset can end up with different parties. This finding was carried over from the prior review and remains behaviourally true in the current code.
Resolved
#5 medium Issue
Whitelisted users blocked from funding in phases without tiers
A prior review found that whitelisted users could not fund in phases configured without tier limits because of an out-of-bounds access. The current code separates the whitelist and tier branches and no longer indexes the tier array for whitelisted buyers.
Resolved
#6 medium Issue
Pool parameters can be changed mid-sale
A prior review found that the pool parameters could be changed after the sale started. The current code blocks changes once minting has begun.
Resolved
#7 medium Issue
Phase parameters can be changed while active or after completion
A prior review found that phase parameters could be modified during or after a phase. The current code blocks phase updates once minting has begun.
Resolved
#8 medium Issue
Gift theft via front-running due to unbound signature verification
A prior review found that the gift assignment signature did not bind to the recipient, allowing front-running. The current code binds the signature to the recipient address.
Resolved
#9 medium Issue
Permanent asset lockout after claim phase expiration
A prior review found that assets could be permanently locked if the claim phase expired. The claim function tied to that behaviour has been removed and the distribution model changed.
low Issues | 6 findings
Pending
#1 low Issue
Initialization does not fully validate pool and phase parameters
The initializer assigns the pool struct and pushes each phase directly, without the checks that the dedicated setters perform later. A deployment can therefore start with a zero price, a zero maximum supply, an excessive buying fee or phases whose start time is not before their end time. Some of these states cannot be corrected afterwards because the setters are locked once minting begins, so a misconfiguration at launch can leave the sale permanently broken.
Pending
#2 low Issue
Buying fee can be configured up to one hundred percent
The buying fee is only checked against the basis-points denominator, which means it can be set as high as one hundred percent. At that level a buyer would pay twice the nominal price for each NFT. The fee is fixed before minting starts and is visible on-chain, which limits the risk, but there is no upper bound near a reasonable level, so the configuration permits a fee far above any normal surcharge.
Pending
#3 low Issue
Interleaving pre-mint and withdrawal can break the distributable range
Distribution hands out token ids from the bottom of the pre-minted pool while withdrawal removes them from the top, relying on a single cursor and a contiguity assumption. Calling the pre-mint function again after some tokens were withdrawn, or withdrawing after several pre-mints, creates holes in the range. A later distribution or withdrawal can then try to move a token the contract no longer owns, which reverts and can stall funding or withdrawals until the state is manually repaired.
Pending
#4 low Issue
Relayer sender extraction relies on a brittle trusted-signer pattern
When the caller is the whitelist signer, the contract treats the last twenty bytes of calldata as the real sender. This homemade relay pattern depends entirely on the backend appending the address correctly, and it conflates two roles since the signer is both the relayer and the authority that signs whitelist and gift approvals. The funding path is protected because relayed calls still require the user's own payment authorization, but the pattern is fragile and means the signer can never make a normal direct call to these functions without the sender being misread.
Pending
#5 low Issue
Broad privileged control concentrated in the factory owner and managers
Ownership is transferred to the factory at initialization, and a set of managers shares many day-to-day powers. Between them these roles can withdraw the raised funds and undistributed NFTs, rotate the signer, whitelist operators, set the base URI and move the withdrawal cursor. There is no timelock and no on-chain multisig requirement at the contract level, so the security of buyer funds and assets rests on the factory contract, which governs ownership and was not part of this review.
Resolved
#6 low Issue
Missing zero or dead address check
A prior review noted that some address setters did not check for the zero or dead address. The current code adds these checks on the relevant setters.
optimization Issues | 4 findings
Pending
#1 optimization Issue
Inherited availability is recomputed in a loop on every purchase
Each funding call recomputes the rolled-over availability by looping backward over every preceding phase. Because this runs on the core funding path, the gas cost grows with the number of phases that have elapsed, making later participation progressively more expensive. This finding was carried over from the prior review and is still present.
Pending
#2 optimization Issue
Loop and storage micro-optimizations
Several loops read storage array lengths on each iteration and increment counters with checked arithmetic, a few custom errors are declared but never used, and the reentrancy guard is not always the first modifier. None of these affects correctness, but addressing them lowers gas and improves clarity.
Resolved
#3 optimization Issue
Gas griefing via inefficient claim loop
A prior review flagged a claim loop that grew with a lender's purchase history. That claim function has been removed in the current design.
Resolved
#4 optimization Issue
Rarity update relied on an unsorted phases array for its time check
A prior review noted that the rarity update used a fixed phase index to decide whether the sale had started. The current code uses the minting state instead.
informational Issues | 7 findings
Pending
#1 informational Issue
Lender claimable counter is never written and always reads zero
The mapping that tracks claimable NFTs per lender is read in the status views but is never assigned anywhere in the contract, so it always returns zero. It appears to be a leftover from the removed claim flow. The exposed value is misleading to any integrator that reads it.
Pending
#2 informational Issue
Phase selection and rollover assume the phases array is ordered
The current-phase lookup scans from the highest index down and returns the first match, and the availability rollover treats lower-indexed phases as chronologically earlier. If phases are configured out of order or with overlapping windows, both behave unexpectedly. There is no on-chain enforcement of ordering, so correctness depends on careful configuration.
Pending
#3 informational Issue
Administrative actions are coupled to factory availability
Many administrative functions forward a notification to the factory as a direct external call, and most of them do not guard against that call reverting, unlike the transfer hook which wraps its forwarder. Because the factory is the owner this is a controlled dependency, but a faulty or paused factory could block manager and owner operations, and several state changes are only observable through the factory rather than through local events.
Pending
#4 informational Issue
Code quality and documentation issues
The code contains comments in a non-English language, some NatSpec blocks omit parameters that the functions actually take, and a few declared custom errors are never used. None of this affects behaviour, but it reduces readability and consistency.
Pending
#5 informational Issue
Ownership uses a single-step transfer model
The contract uses the single-step ownership model. Ownership currently rests with the factory, which mitigates the usual risk of a mistyped transfer, but if ownership is ever moved to an externally owned account a single-step transfer offers no protection against handing control to a wrong or unrecoverable address.
Resolved
#6 informational Issue
Floating pragma solidity version
A prior review recommended pinning the compiler version. The current code pins an exact version.
Pending
#7 informational Issue
Missing input validation in initialize function
A prior review found that the initializer lacked validation. The current code validates the address parameters but still does not fully validate the pool values or the phase time ranges.