Introduction
We express our gratitude to the Zoth team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.
Zoth is a retail-focused RWA ecosystem that is bringing fixed-yield generating, institutional grade, high-quality RWAs on-chain. Zoth allows users to collateralize their off-chain or on-chain tokenized assets (TBILLs, ETFs, MMFs etc.) to issue ZeUSD, a yield bearing stable token, which can unlock DeFi access on top of existing RWAs.
Document | |
---|---|
Name | Smart Contract Code Review and Security Analysis Report for Zoth |
Audited By | Kornel Światłowski, Nataliia Balashova |
Approved By | Grzegorz Trawinski |
Website | https://zoth.io→ |
Changelog | 30/12/2024 - Preliminary Report; 02/01/2025 - Final Report |
Platform | Ethereum |
Language | Solidity |
Tags | Token Sales, Upgradable |
Methodology | https://hackenio.cc/sc_methodology→ |
Document
- Name
- Smart Contract Code Review and Security Analysis Report for Zoth
- Audited By
- Kornel Światłowski, Nataliia Balashova
- Approved By
- Grzegorz Trawinski
- Website
- https://zoth.io→
- Changelog
- 30/12/2024 - Preliminary Report; 02/01/2025 - Final Report
- Platform
- Ethereum
- Language
- Solidity
- Tags
- Token Sales, Upgradable
- Methodology
- https://hackenio.cc/sc_methodology→
Review Scope | |
---|---|
Repository | https://github.com/0xZothio/zeusd-contracts→ |
Commit | a0842125be71adf3784ba91b45fd3476a2ceb7d9 |
Remediation commit | 75a10af095e97785f0a3ed410f91cf02432e171c |
Review Scope
- Commit
- a0842125be71adf3784ba91b45fd3476a2ceb7d9
- Remediation commit
- 75a10af095e97785f0a3ed410f91cf02432e171c
Audit Summary
The system users should acknowledge all the risks summed up in the risks section of the report
Documentation quality
Functional requirements are present, but only at a high-level.
Technical description has some gaps.
Code quality
Best practice violations.
Unused functions.
Insufficient Gas modeling.
Test coverage
Code coverage of the project is 17.91% (branch coverage).
Negative cases coverage is missed.
Interactions by several users are not tested thoroughly.
ZeUSD_Router and USD0PPSubVault contracts are not tested at all.
System Overview
The ZeUSD_Router serves as the central interface for interacting with the ZeUSD protocol. It enables users to mint ZeUSD by depositing collateral or stablecoins, bridge ZeUSD across different blockchains, and burn ZeUSD to retrieve their collateral. Only the whitelisted addresses can mint and burn ZeUSD tokens. The ZeUSD_Router interacts with both the CollateralVault and SubVaults to facilitate these functions.
The CollateralVault manages the registry of SubVaults and their collateral configurations, coordinates price data for ZeUSD minting, and tracks user deposits. Only the ZeUSD_Router contract can invoke deposit-related functions within the CollateralVault.
The USD0PPSubVault contract stores USD0++ tokens used for minting ZeUSD. It interacts with the price oracle to retrieve the current token price. Although the contract inherits from the ISubVault interface, it does not support adding additional assets, and related functions are disabled.
The system consists of a single ZeUSD_Router, one CollateralVault, and multiple SubVaults, each handling specific collateral types within the protocol.
Privileged roles
The ZeUSD_Router contract uses the AccessControlUpgradeable library from OpenZeppelin to restrict access to important functions.
ADMIN_ROLE
can:
Sets whitelist status for an account
Sets multiple whitelist statuses
Sets global deposit pause status
Updates LayerZero adapter
Sets and rests approval for LayerZero adapter
DEFAULT_ADMIN_ROLE
can:
Grants and revokes all roles
Authorizes contract upgrades
Can perform all admin functions
The CollateralVault contract uses the AccessControlUpgradeable library from OpenZeppelin to restrict access to important functions.
ADMIN_ROLE
can:
Sets the router address
Registers or updates a subvault configuration
Updates specific parameters of a subvault
Removes a subvault registration
Pauses vault operations
Unpauses vault operations
DEFAULT_ADMIN_ROLE
can:
Grants and revokes all roles
Authorizes contract upgrades
Can perform all admin functions
The USD0PPSubVault contract uses the AccessControl library from OpenZeppelin to restrict access to important functions.
ADMIN_ROLE
can:
Sets oracle for an asset
Adds support for a secondary asset
Removes support for a secondary asset
Enables emergency mode
Disables emergency mode
Executes emergency withdrawal
Pauses vault operations
Unpauses vault operations
Potential Risks
Scope Definition and Security Guarantees: The audit does not cover all code in the repository. Contracts outside the audit scope may introduce vulnerabilities, potentially impacting the overall security due to the interconnected nature of smart contracts.
System Reliance on External Contracts: The functioning of the system significantly relies on specific external contracts. Any flaws or vulnerabilities in these contracts adversely affect the audited project, potentially leading to security breaches or loss of funds.
Arbitrary Oracle Address Setting by Admin: Allowing the admin to set oracle addresses without constraints or verification mechanisms introduces the risk of incorrect or malicious oracle selection, affecting the accuracy of data and potentially leading to financial losses.
Owner's Unrestricted State Modification: The absence of restrictions on state variable modifications by the owner leads to arbitrary changes, affecting contract integrity and user trust, especially during critical operations like minting phases.
Flexibility and Risk in Contract Upgrades: The project's contracts are upgradable, allowing the administrator to update the contract logic at any time. While this provides flexibility in addressing issues and evolving the project, it also introduces risks if upgrade processes are not properly managed or secured, potentially allowing for unauthorized changes that could compromise the project's integrity and security.
Absence of Upgrade Window Constraints: The contract suite allows for immediate upgrades without a mandatory review or waiting period, increasing the risk of rapid deployment of malicious or flawed code, potentially compromising the system's integrity and user assets.
The USD0PPSubVault
contract assumes the ERC-20 token in the USD0PP
variable is a stablecoin with a Chainlink price oracle using a 24-hour heartbeat. The getOraclePrice()
function enforces this assumption with a hardcoded 24-hour check. If a token with a different heartbeat interval is assigned during contract construction, stale price data may be returned, compromising the accuracy and reliability of the contract's price data.
Findings
Code ― | Title | Status | Severity | |
---|---|---|---|---|
F-2024-7804 | Missing Validation of Collateral Amount Allows User to Drain SubVault From All Tokens | fixed | Critical | |
F-2024-8013 | Inconsistent Handling of StableCoins and Non-StableCoins in Mint Functions | accepted | Medium | |
F-2024-8000 | The withdrawEmergency() Allows Withdrawal of Active Collateral Deposits | accepted | Medium | |
F-2024-7992 | ADMIN_ROLE Can Block Burn Operations and Withdraw Assets | accepted | Medium | |
F-2024-7877 | ADMIN_ROLE Can Front-Run Mint Functions | accepted | Medium | |
F-2024-8040 | Unrestricted Deposit Removal by ADMIN_ROLE in CollateralVault | accepted | Medium | |
F-2024-8004 | Undefined Decimal Precision for LTV and Price Fields in CollateralDetails | fixed | Low | |
F-2024-7820 | Oracle Price Decimal Format Not Validated in setAssetOracle | accepted | Low | |
F-2024-8042 | The removeDeposit() Function Reverts or Emits Incorrect Events | fixed | Low | |
F-2024-7858 | Missing Revert Allows Collateral Deposit Without Minting ZeUSD | fixed | Low |
Identify vulnerabilities in your smart contracts.
Appendix 1. Definitions
Severities
When auditing smart contracts, Hacken is using a risk-based approach that considers Likelihood, Impact, Exploitability and Complexity metrics to evaluate findings and score severities.
Reference on how risk scoring is done is available through the repository in our Github organization:
Severity | Description |
---|---|
Critical | Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation. |
High | High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation. |
Medium | Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category. |
Low | Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution. |
Severity
- Critical
Description
- Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation.
Severity
- High
Description
- High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation.
Severity
- Medium
Description
- Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category.
Severity
- Low
Description
- Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution.
Potential Risks
The "Potential Risks" section identifies issues that are not direct security vulnerabilities but could still affect the project’s performance, reliability, or user trust. These risks arise from design choices, architectural decisions, or operational practices that, while not immediately exploitable, may lead to problems under certain conditions. Additionally, potential risks can impact the quality of the audit itself, as they may involve external factors or components beyond the scope of the audit, leading to incomplete assessments or oversight of key areas. This section aims to provide a broader perspective on factors that could affect the project's long-term security, functionality, and the comprehensiveness of the audit findings.
Appendix 2. Scope
The scope of the project includes the following smart contracts from the provided repository:
Scope Details | |
---|---|
Repository | https://github.com/0xZothio/zeusd-contracts→ |
Commit | a0842125be71adf3784ba91b45fd3476a2ceb7d9 |
Remediation commit | 75a10af095e97785f0a3ed410f91cf02432e171c |
Whitepaper | - |
Requirements | https://docs.google.com/document/d/14nwJD55OjzAgiy82sCeyxQ5WefFnF6AVGPKJYGCjXc8/edit?usp=sharing→ |
Technical Requirements | https://docs.google.com/document/d/14nwJD55OjzAgiy82sCeyxQ5WefFnF6AVGPKJYGCjXc8/edit?usp=sharing→ |
Scope Details
- Commit
- a0842125be71adf3784ba91b45fd3476a2ceb7d9
- Remediation commit
- 75a10af095e97785f0a3ed410f91cf02432e171c
- Whitepaper
- -
Assets in Scope
Appendix 3. Additional Valuables
Verification of System Invariants
During the audit of Zoth / Zeusd-Contracts, Hacken followed its methodology by performing fuzz-testing on the project's main functions. Foundry →, a tool used for fuzz-testing, was employed to check how the protocol behaves under various inputs. Due to the complex and dynamic interactions within the protocol, unexpected edge cases might arise. Therefore, it was important to use fuzz-testing to ensure that several system invariants hold true in all situations.
Fuzz-testing allows the input of many random data points into the system, helping to identify issues that regular testing might miss. A specific Echidna fuzzing suite was prepared for this task, and throughout the assessment, 5 fuzz scenarios were tested over 1M runs each. This thorough testing ensured that the system works correctly even with unexpected or unusual inputs.
Invariant | Test Result | Run Count |
---|---|---|
Mint ZeUSD with random amount of USD0++ and price 1 | Passed | 1M |
Mint ZeUSD with random amount of USD0++ and price 0.5 | Passed | 1M |
Mint ZeUSD with random amount of USD0++ and price 100 | Passed | 1M |
Burn random amount of ZeUSD | Passed | 1M |
Mint ZeUSD with random LTV | Passed | 1M |
Invariant
- Mint ZeUSD with random amount of USD0++ and price 1
Test Result
- Passed
Run Count
- 1M
Invariant
- Mint ZeUSD with random amount of USD0++ and price 0.5
Test Result
- Passed
Run Count
- 1M
Invariant
- Mint ZeUSD with random amount of USD0++ and price 100
Test Result
- Passed
Run Count
- 1M
Invariant
- Burn random amount of ZeUSD
Test Result
- Passed
Run Count
- 1M
Invariant
- Mint ZeUSD with random LTV
Test Result
- Passed
Run Count
- 1M
Additional Recommendations
The smart contracts in the scope of this audit could benefit from the introduction of automatic emergency actions for critical activities, such as unauthorized operations like ownership changes or proxy upgrades, as well as unexpected fund manipulations, including large withdrawals or minting events. Adding such mechanisms would enable the protocol to react automatically to unusual activity, ensuring that the contract remains secure and functions as intended.
To improve functionality, these emergency actions could be designed to trigger under specific conditions, such as:
Detecting changes to ownership or critical permissions.
Monitoring large or unexpected transactions and minting events.
Pausing operations when irregularities are identified.
These enhancements would provide an added layer of security, making the contract more robust and better equipped to handle unexpected situations while maintaining smooth operations.