Quantstamp reviewed ZNS Token Upgrade (Zero Name Service (ZNS)) on 17 Nov 2023: 18 findings, 0 critical; 10 marked fixed, 7 acknowledged, 1 open.
Report hosted on certificate.quantstamp.com.
Trustblock does not review code.
Statuses are the security firm’s own, from its report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 0 | 0 | 1 |
| Medium | 0 | 3 | 3 |
| Low | 1 | 4 | 6 |
The `ZNSSubRegistrar` contract provides a setter function, `setPricerContractForDomain()`, allowing the domain owner/operator to change the pricer contract for a specific domain. With this ability, a malicious domain owner could potentially front-run a domain purchase transaction, swapping out the pricer contract for one that charges an unexpectedly high price. This is problematic if a user purchasing the domain approves a transaction for a significantly higher amount than required or unlimited approval, as they may end up being charged much more than anticipated.
The primary concern identified in the `ZNSCurvePricer._getPrice()` function is the potential incompatibility between the `precisionMultiplier` and the token's decimals, leading to incorrect pricing calculations. This incompatibility can result in a significant loss of precision, especially evident when using a high `precisionMultiplier` (e.g., 10^18) with tokens that have a lower decimal precision (e.g., USDC with 6 decimal places). This precision loss can result in the computed price being truncated to zero, as demonstrated in the given exploit scenario.
The `ZNSTreasury.stakeForDomain()` function accounts for staked amounts based on the tokens deposited. If deflationary tokens, which automatically subtract fees on transfer, or rebasing tokens, which can adjust balances algorithmically, are used, this can lead to discrepancies between the recorded `stakedForDomain.stakedAmount` and the actual reserve. Furthermore, since the protocol accepts any token, a malicious token could exacerbate this discrepancy. These inaccuracies can lead to insolvency issues during unstaking.
The documentation denotes the structure `wilder.wapes`, indicating that `wilder` is the root domain and `wapes` is its subdomain. This portrayal is in contrast with the traditional way domains and subdomains are represented. Typically, given the full string `wilder.wapes`, `wilder` would be the subdomain, and `wapes` would be the domain.
The protocol contracts contain a setter function to update the registry contract. If the address of the registry contract is updated and missed for one of the contracts, it can lead to a mismatched registry across the different contracts. This mismatch is concerning since the registry plays a pivotal role in determining privileged roles, domain ownership, and associated operations. Consequently, if the registry is mismatched, it could disrupt the control and permissions system, affecting which functions are accessible when updating configurations. This is an information issue because it is a limitation of the design choice.
The ownership transfer process of a `domainHash` in the protocol requires two distinct actions: transferring the corresponding ERC721 token and calling the `ZNSRootRegistrar.reclaimDomain()` function. This approach introduces a potential oversight issue. If an owner transfers the ERC721 token but the new owner fails to immediately invoke `reclaimDomain()`, there exists a window of time where the original owner or operator, despite not having the ERC721 token, retains the ability to make impactful changes via the `ZNSSubRegistrar` contract. During this window, the previous owner or operator could, for instance, update configuration settings through methods such as `setDistributionConfigForDomain()` and `setPricerContractForDomain()`.
While upgradeability is not a vulnerability in itself, users of the ZNS protocol should be aware that many contracts in the system can be upgraded at any time. This carries certain risks, as upgrading contracts is a delicate operation that can introduce bugs, regressions, and other undesirable code. It is important to note that this audit does not guarantee the behavior of future contracts that the protocol may be upgraded to. Here is a list of contracts that have been explicitly marked as upgradeable (please note that the list might not be exhaustive): ```bash ▶ grep -rl --exclude="I*" --exclude-dir="mocks" "function initialize" contracts contracts/token/ZNSDomainToken.sol contracts/registrar/ZNSSubRegistrar.sol contracts/registrar/ZNSRootRegistrar.sol contracts/price/ZNSFixedPricer.sol contracts/price/ZNSCurvePricer.sol contracts/registry/ZNSRegistry.sol contracts/treasury/ZNSTreasury.sol contracts/resolver/ZNSAddressResolver.sol ```
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (129)
236 projects reviewed · 332 reports · latest Oct 2026
See Quantstamp’s auditsSomething wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.
Tell us