OZONE CHAIN Info
Ozone Chain is a forward thinking blockchain platform designed to leverage the advantages of the Proof of Stake (PoS) consensus mechanism. It aims to offer a secure, scalable, and sustainable environment for decentralized applications (dApps). The vision of Ozone Chain is to foster a decentralized ecosystem that empowers users, developers, and enterprises to innovate and create value through transparent and inclusive governance.
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 can blacklist addresses
It is 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 can be burned
There is a function to burn tokens in the contract without any allowances.
Ownership is renounced
The contract does not include owner functions that allow post-deployment modifications.
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.
_onlyDAOAuth), ensuring that no single administrator can unilaterally execute these actions without decentralized consensus. The system now demonstrates a significantly improved security maturity.Files and details
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Findings and Audit result
critical Issues | 4 findings
Resolved
#1 critical Issue
Fragile Calldata Encoding
safeCallBytes() and safeStaticCall() use abi.encodePacked(abi.encodeWithSignature(sig), args) to construct calldata. This non-standard encoding is fragile: abi.encodeWithSignature(sig) produces only the 4-byte selector (no params), then abi.encodePacked appends raw args. This only works because all callers happen to pre-encode with abi.encode(). If any caller passes unpadded bytes, the call silently receives corrupted data. Additionally, abi.encodePacked with multiple dynamic types creates hash collision risk per Solidity docs. These helpers are used by EVERY contract in the system for ALL cross-contract communication.
Resolved
#2 critical Issue
Silent Security Failure
_isSafe(), _isSecureBase(), and _isSigner() delegate to safeBoolReturn() which returns false (default) on ANY failure: target destroyed, hexbase unset, safeguard bricked, network issue, etc. A false return from _isSafe() causes ALL _onlyIsSafe/_onlyOwner/_onlyDAOAuthOrSecureBase modifiers to revert, permanently bricking the entire system. Conversely, corrupted return data could cause auth checks to pass incorrectly. There is zero diagnostic information when failures occur.
Resolved
#3 critical Issue
Spoofable Bytecode Authentication
_onlyInstance and _onlyStor modifiers authenticate callers by comparing keccak256 of their deployed bytecode against a reference contract. Since all instances are created via Clones.clone(), ALL clones share identical bytecode. An attacker can deploy their own contract with the same bytecode (or even use CREATE2 to deploy a minimal proxy pointing to the same implementation) and bypass authentication. This grants unauthorized access to functions like join(), addBusiness(), claimIncome(), and updateUsers().
Resolved
#4 critical Issue
Missing Access Control
hexBase.isLogging(bool flag) has no access control -- anyone can call it to change the DEBUG state variable. While DEBUG currently appears informational, this demonstrates a pattern of missing access control on the central registry contract. Additionally, hexBase.submit() has no access control beyond the insafeguard==address(0) check, meaning the FIRST caller to submit() permanently configures the entire system including setting themselves as inroot.
high Issues | 7 findings
Resolved
#1 high Issue
Divide-Before-Multiply Precision Loss
_computePoolAdjustments() performs sequential division-then-multiplication: bs1 = (bs * stakeN) / (stakeD * 100), bs2 = (bs1 * roiN) / (roiD * 100), tvl = roiEnd * bs2. For small bs values, intermediate results round to zero, causing zero TVL allocation and zero LSB adjustments. This systematically under-reports ROI for small depositors.
Resolved
#2 high Issue
Owner Always Zero
OwnerBase constructor explicitly sets _owner = address(0). The _onlyOwner modifier checks _owner == msg.sender, making it permanently unsatisfiable in OwnerBase itself. Inheriting contracts must manually set _owner (e.g., InstanceStor.preinit sets _owner=_own), but any contract that forgets to set _owner has a permanently locked _onlyOwner check. This is a fragile pattern with no enforcement or compiler warning.
Resolved
#3 high Issue
No-Op Internal Function
hexBase.updateAddress(address storageVar, address newAddr) takes storageVar as a value parameter, not a storage pointer. The assignment storageVar = newAddr only modifies the local copy on the stack and has zero effect on state. This function is dead code. If any logic was intended to use it for address updates, those updates silently do nothing.
Resolved
#4 high Issue
Variable Assignment Bug
setClaimPerDay(uint256 _min, uint256 _max) sets minClaimPerDay twice: minClaimPerDay = _min (line 248) then minClaimPerDay = _max (line 249). maxClaimPerDay is never updated. This means maxClaimPerDay is stuck at its initial value of 10000e18 and cannot be changed by governance.
Resolved
#5 high Issue
Incorrect Boolean Logic
isNodeStopped() returns (!isUser) || (isSuspend && isLock && !isUser). The second condition (isSuspend && isLock && !isUser) is logically subsumed by the first (!isUser). If isUser is true, the function always returns false regardless of suspend/lock status. This means a suspended AND locked node is NOT considered stopped, breaking the suspension mechanism for existing users.
Resolved
#6 high Issue
Compilation Error
DeployFactory.sol does not compile due to missing semicolon on line 15 (HexBaseUserEngine=_hexUserEngine has no semicolon) and a variable name mismatch (declared as HhexBaseUserEngine with double-H on line 11, but used as HexBaseUserEngine on line 15). This contract was never compiled or tested in its current form.
Resolved
#7 high Issue
Compilation Error - Undeclared Variable
mapDelegator() uses undeclared variable 'sig' in abi.encodeWithSignature(sig) on line 70. This is a compilation error -- the contract cannot be deployed. The function signature string is missing entirely.
medium Issues | 9 findings
Resolved
#1 medium Issue
No Events Emitted
OwnerBase emits zero events across all 225 lines. No events for ownership changes, ETH transfers via _transfer(), ETH burns via Burn(), or hexbase updates via _ownerbase(). This makes off-chain monitoring, incident response, and forensic analysis impossible. Slither and Aderyn together flagged 55+ instances of state changes without events across the codebase.
Resolved
#2 medium Issue
Deprecated transfer() Usage
_transfer() uses payable(to).transfer(amount) which forwards only 2300 gas. This will fail if the recipient is a contract with a non-trivial receive/fallback function, or on chains with different gas pricing. Affects: OwnerBase._transfer(), Burn(), InstanceStor.BurnCoin(), InstanceMe.forceTransfer(), TreaseryTVLFactory.transfer().
Resolved
#3 medium Issue
Missing Zero-Address Validation
16+ functions accept address parameters without zero-address validation. Critical instances: InstanceStor.preinit() sets _owner without checking, updateOwner() can set owner to zero permanently locking the contract, OzoneTreasury constructor doesn't validate _backend. Slither flagged 16 instances.
Resolved
#4 medium Issue
External Calls Inside Loops
Multiple functions make unbounded external calls inside loops: _computeRoyality() calls hexbase.in741() and hexbase.in741Rule() for each rank iteration, _importOld() calls hexbase.mapOldORC1155() and hexbase.inOrc1155() per mint, TransferRequests.importuser() calls safeAddressReturn() and proxyCall() per node. This creates unbounded gas consumption, potential out-of-gas DoS, and amplifies reentrancy risk.
Resolved
#5 medium Issue
Confusing Access Control Logic
_onlyDelegators modifier uses: require((sgn || saf) && (sgn || nd)). This simplifies via Boolean algebra to: sgn || (saf && nd). A signer always passes regardless of delegator node status. If _isSafe() returns false (safeguard down), NO delegator can vote, permanently bricking DAO governance. The complex expression obscures this critical dependency.
Resolved
#6 medium Issue
ETH Distribution Rounding Loss
In _txnType1(), ETH is split: 70% to factory, 21% to reward, 4.5% to royality, 4.5% to tour. Due to integer division, the sum may be less than msg.value. Remaining wei are permanently locked in the InstanceMe contract with no recovery mechanism. Fuzz test F-12 confirms dust loss for most input values.
Resolved
#7 medium Issue
Empty Initialize Function
hexBase.initialize() is a payable external function that checks insafeguard==address(0) but then does nothing (empty body). Any ETH sent to this function is absorbed by hexBase with no state change. The function name suggests it should perform initialization, but all actual init logic is in submit().
Resolved
#8 medium Issue
ETH Sent to Zero Address
Burn() function uses payable(address(0)).transfer(amount) instead of DEAD address to destroy ETH. The same anti-pattern exists in InstanceStor.BurnCoin() at line 332.
Resolved
#9 medium Issue
Reentrancy Vulnerabilities
Slither identified 12+ reentrancy instances and Aderyn confirmed 16 instances. State variables (rankCount, mintCount, lvlbs, lvlqty, LSB, _ageNow, postInit, UserToId, nested, isForce, forms, UserToForm) are written AFTER external calls via proxyCall() which uses target.call{value:}(data) forwarding all gas. An attacker can re-enter during these calls to manipulate ranks, income calculations, mint counts, and NFT balances.
low Issues | 12 findings
Resolved
#1 low Issue
Floating Pragma
All 14 Solidity files use pragma solidity ^0.8.20 (floating). This can lead to compilation with a newer, potentially incompatible compiler version. Best practice is to pin to an exact version for production deployments.
Resolved
#2 low Issue
Dead Code
Three internal functions are never called: safeUintReturn1() (duplicate of safeUint256Return), safeStringReturn(), and delegateCall(). Dead code increases attack surface (delegateCall is particularly dangerous if ever exposed) and wastes deployment gas.
Resolved
#3 low Issue
Variable Shadowing
Three functions in InstanceStor shadow OwnerBase._age() with local parameter _age: moveLvlIncome(), addLevelnGetRank(), and _setRank(). This can cause confusion and unintended behavior if the developer intended to call the function but accidentally referenced the parameter.
Resolved
#4 low Issue
Variable Shadowing
ORC1155 constructor and postinit() have local variables that shadow inherited state variables from ERC1155 and OwnerBase. This is flagged by Aderyn L-8.
Resolved
#5 low Issue
Unused State Variable
InstanceStor declares uint256 private royl at line 65 which is never read or written. This wastes a storage slot (cost: 20,000 gas on first write).
Resolved
#6 low Issue
signerCallback Sets _safe=false
libSafeguard.signerCallback() modifies a signer AND sets _safe=false as a side-effect. This means any signer change immediately disables the entire system's _isSafe() check, requiring a separate approveSafe(true) call. This coupling is risky: if the DAO forgets to re-approve, the system is bricked.
Resolved
#7 low Issue
Independent Access Control
lib741Price uses its own _owners mapping for access control, completely independent of the OwnerBase/hexBase/libSafeguard system. This creates a separate admin surface that doesn't benefit from the DAO governance or safeguard checks. The constructor owner could unilaterally change prices.
Resolved
#8 low Issue
Custom Ownable Without Renounce/Transfer
BinanceDeposits.sol defines a custom Ownable contract with owner set in constructor and no transferOwnership function. If the owner private key is compromised or lost, the LiquidityVault and ExpensesVault are permanently locked or compromised with no recovery path.
Resolved
#9 low Issue
Unprotected addMock Function
HexBaseDaoCoreDeployer.addMock() has no access control. Anyone can call it to change the old741 and price addresses used during system initialization. While the deployer contract is used once during setup, if its address is known, an attacker could front-run initialization.
Resolved
#10 low Issue
Modifiers Used Only Once
Five modifiers are used only once: _onlyThis, _onlyStor, _onlyDelegators, _onlySigner, and OzoneTreasury.onlyBackend. Single-use modifiers add code size and deployment cost without reusability benefit. Aderyn L-9 flagged this.
Resolved
#11 low Issue
Unsafe ERC20 Operations
LiquidityVault.withdraw() and ExpensesVault.withdraw() use raw IBEP20.transfer() and transferFrom() without SafeERC20. Some tokens don't return bool (USDT on mainnet), which would cause these calls to revert. While this targets BEP20/OzoneChain, using SafeERC20 is defensive best practice.
Resolved
#12 low Issue
Dangerous Unary Operator
Aderyn H-3 flagged _uid=++nodeCount as a potentially mistaken unary operator. While =++ is likely intentional (pre-increment then assign), the compact syntax can be confused with =+ (which acts as assignment, not increment). This should be split for clarity.
informational Issues | 8 findings
Resolved
#1 informational Issue
No NatSpec Documentation
Zero NatSpec documentation exists across the entire codebase. No @notice, @dev, @param, or @return annotations on any function. This makes code review, integration, and maintenance significantly harder.
Resolved
#2 informational Issue
Directory Naming Typo
The directory 'componant/' is misspelled (should be 'component'). This affects import paths and developer experience.
Resolved
#3 informational Issue
Broken Test Imports
Both test files reference a non-existent path '../src_19JulyUpdated01Jan/'. This means the test suite cannot compile and there is effectively ZERO test coverage for the current codebase.
Resolved
#4 informational Issue
Duplicate File
'lib/hexBase copy.sol' is a duplicate of hexBase.sol with a different submit() implementation. Manual file copies instead of version control indicate poor development practices and can cause confusion about which version is authoritative.
Resolved
#5 informational Issue
Incorrect Source Path
foundry.toml specifies src='src' but no src/ directory exists. Source files are spread across core/, lib/, componant/, DAO/, swap/, and deploy/. This indicates the project was extracted without maintaining the original Foundry project structure.
Resolved
#6 informational Issue
Typo in Variable Name
The mapping for authorized signers is named 'singers' (typo of 'signers'). While functionally harmless, this indicates code quality concerns and makes the code harder to understand.
Resolved
#7 informational Issue
Unused Struct
PoolCoinValidator struct is defined with identical fields to PoolCoin but is never used anywhere in the codebase. The actual validator pools use PoolCoin type (poolValprivate, poolValpublic).
Resolved
#8 informational Issue
Front-Running Risk on submit()
hexBase.submit() can be called by anyone before insafeguard is set (checked by require(insafeguard==address(0x0))). The first caller permanently configures the entire system and becomes inroot. If the hexBase contract is deployed and the submit() transaction is visible in the mempool, an attacker can front-run it to hijack the entire system configuration.