Hashgraph Name Protocol Audit Report
Copyright © 2022 by Verilog Solutions. All rights reserved.August 11, 2022
by Verilog Solutions
This report presents our engineering engagement with the PieFi dev team on their name service protocol based on Hedera – the Hashgraph Name Protocol.
Project Name | Hashgraph Name Protocol |
---|---|
Repository Link | https://github.com/pieFi-platform/hashgraph-name-protocol |
Commit Hash | e938ca0236ba53f3284ab2a135bbb7437a1af443 |
Language | Solidity |
Chain | Hedera |
About Verilog Solutions
About Verilog Solutions
Founded by a group of cryptography researchers and smart contract engineers in North America, Verilog Solutions elevates the security standards for Web3 ecosystems by being a full-stack Web3 security firm covering smart contract security, consensus security, and operational security for Web3 projects.
Verilog Solutions team works closely with major ecosystems and Web3 projects and applies a quality above quantity approach with a continuous security model. Verilog Solutions onboards the best and most innovative projects and provides the best-in-class advisory services on security needs, including on-chain and off-chain components.
Table of Contents
Table of Contents
Service Scope
Service Scope
Service Stages
Service Stages
Methodology
Methodology
- Code Assessment
- We evaluate the overall quality of the code and comments as well as the architecture of the repository.
- We help the project dev team improve the overall quality of the repository by providing suggestions on refactorization to follow the best practice of Web3 software engineering.
- Code Logic Analysis
- We dive into the data structures and algorithms in the repository and provide suggestions to improve the data structures and algorithms for the lower time and space complexities.
- We analyze the hierarchy among multiple modules and the relations among the source code files in the repository and provide suggestions to improve the code architecture with better readability, reusability, and extensibility.
- Access Control Analysis
- We perform a comprehensive assessment of the special roles of the project, including their authorities and privileges.
- We provide suggestions regarding the best practice of privilege role management according to the standard operating procedures (SOP).
- Off-Chain Components Analysis
- We analyze the off-chain modules that are interacting with the on-chain functionalities and provide suggestions according to the SOP.
- We conduct a comprehensive investigation for potential risks and hacks that may happen on the off-chain components and provide suggestions for patches.
Audit Scope
Audit Scope
Project Summary
Project Summary
hashgraph.name is a distributed, open, and extensible naming system built on the Hedera Hashgraph.
Use Case Scenario
Use Case Scenario
Hashgraph Name is an extension of yourself in web3 and around the Hedera ecosystem. Similar to Ethereum’s naming service, you can set your Hashgraph Name as the reverse record for your Hedera wallet address. It ties human-readable names like ‘baird.hbar’ to machine-readable identifiers such as Hedera wallet addresses, other cryptocurrency addresses, content hashes, and metadata.
Findings & Improvement Suggestions
Findings & Improvement Suggestions
Severity | Total | Acknowledged | Resolved |
High | 1 | 1 | 1 |
Medium | 2 | 2 | 1 |
Low | 5 | 5 | 3 |
Informational | 4 | 4 | 2 |
High
High
- Function
extendExpiry
in SLDNode.sol can be called by any person.Severity High Source SLDNode.sol#L100; Status Resolved in commit 7cd9d48906129942436d9c05e939d89bd59dc0df. Description
This is the function used to extend the expiration date of a sub-domain. The function now can be called by anyone. Ideally, the function can only be called by the top-domain owner.
Exploit Scenario
The attacker can call the function arbitrarily to make the sub-level domain chaos.
Recommendations
The function should be protected by the
onlyTLDOwner
modifier.
Results
Resolved in commit 7cd9d48906129942436d9c05e939d89bd59dc0df.
Medium
Medium
- The same SLD hash might be added twice.
Severity Medium Source TLDNode.sol#L78; Status Acknowledged. Description
TLD node might add the same SLD hash record more than one time.
When the top-level domain (TLD) node adds a new second-level domain (SLD) hash record, it first checks if the SLD node is full or not. If it’s full, a new SLD node contract will be created. In this case, when an SLD hash record is being added to the newly created SLD node contract, we have to first check if the SLD hash record to be added has already been there in the old smart contract before adding it to the new one. Since the new SLD node contract does not have SLD hash records of the previous SLD nodes, the same SLD hash record may be added to the newly created SLD node again.
The same issue may also occur when updating the SLD nodes (i.e., registering the expired SLD) for the reason that there might be multiple SLD records with the same SLD hash.
Exploit Scenario
- The SLD hash "Alice" exists on the current SLD node;
- The current SLD node is already full;
- Alice is able to add the same SLD hash "Alice" to the newly created SLD node;
- Now, TLD node exists two same "Alice" hash and each can have different settings and subdomains;
- The process can be repeated.
Recommendations
Please change the code and check if the SLD hash exists first before adding a new record to the existing SLD node or creating any new SLD node.
Results
Acknowledged.
Reply from PieFi team:
“This is a known issue. Hedera is different than other chains in that there are restrictions that limit scalability. The name service is designed to scale with large numbers of SLDNodes, so it is not possible for the TLDNode to search all SLDNodes within the gas limit. As this is a known issue, calls to the TLDNode::registerSLD() function will be restricted to only our backend. Our backend will check for SLD existence before registering a new SLD.”
SubdomainNode.addSubdomain()
has logic flaws.Severity Medium Source SubdomainNode.sol#L67; Status Resolved in commit b3a22e085eac735371064a14e95e972ba721d078. Description
SubdomainNode.addSubdomain()
has a few logic flaws. Some parameters are not used when the subdomain hash already exists and the information of the subdomain cannot be updated if the length of the subdomain hash array reaches the max record limit.The function
SubdomainNode.addSubdomain()
code is as follows:function addSubdomain(bytes32 _subdomainHash, string memory _name, address _owner) external onlySLDNode returns(int32) { require(subdomainHashes.length < maxRecords, "This contract is full, no more records can be added."); if(records[_subdomainHash].owner == address(0)) { subdomainHashes.push(_subdomainHash); names.push(_name); records[_subdomainHash].name = _name; } records[_subdomainHash].owner = _owner; return HederaResponseCodes.SUCCESS; }
- If the
_subdomainHash
exists in therecords
mapping, the parameter_name
is never used. The subdomain’s name cannot be updated after being created.
- The function will revert when the subdomain hash length reaches the max record limit. The information like
owner
of the existing subdomain cannot be updated.
- If the
Exploit Scenario
- The subdomain hash length reaches the max record limit.
- Alice cannot update the subdomain’s owner because the function reverts.
Recommendations
- Please consider checking if the length of
subdomainHashes
array exceeds the max record limit or not only when adding a new subdomain.
- Please double-check and confirm that the
name
does not need to be updated.
- Please consider checking if the length of
Results
The 1st issue is that the
_name
argument is unused in a specific case.Reply from PieFi team:
“This is intentional. The subdomain contract was designed to be as lean as possible. The
_name
parameter here is the text form of the_subdomainHash
. If the subdomain already exists, then there is no reason to update the name.”The 2nd issue is that there were flaws in the logic of the function. Those flaws have been resolved in commit b3a22e085eac735371064a14e95e972ba721d078.
Low
Low
- The second-level domain can only have limited subdomains.
Severity Low Source SLDNode.sol#L125; Status Acknowledged. Description
SLDNode.addSubdomain()
will revert if the corresponding subdomain node reaches the max record limit.According to the contract code, every second-level domain will only have one subdomain node to maintain the subdomain record. No more subdomain can be added to the second level domain if the amount of subdomains maintained by the subdomain node reaches the max record limit.
Exploit Scenario
N/A
Recommendations
Create a new subdomain node for a second-level domain when a single subdomain node reaches the max record limit.
Results
Acknowledged.
Reply from PieFi team:
“This is intentional. In our testing, we found that the Subdomain.sol contract can store more than 2000 subdomains before the contract runs out of space. We find this is an acceptable limitation.”
- Domain expiry date extension does not check if the SLD hash exists.
Severity Low Source SLDNode.sol#L90; Status Resolved in commit b3a22e085eac735371064a14e95e972ba721d078. Description
SLD hash existence is not checked when extending the expiry date.
SLDNode.extendExpiry()
does not check if the SLD hash record exists or not. SLD hash record that does not exist will have an expiry date after calling this function.
Exploit Scenario
N/A
Recommendations
Check if the SLD hash record exists before extending the expiry date.
Results
Resolved in commit b3a22e085eac735371064a14e95e972ba721d078.
- Using
selfdestruct
is not recommended.Severity Low Source HNS protocol Status Resolved in commit b3a22e085eac735371064a14e95e972ba721d078. Description
The function
selfdestruct
is used in multiple contracts. Consider removing the self-destruct functionality unless it is absolutely requiredUsing
selfdestruct
makes the contract a suspicious metamorphic contract and places users under contract re-init risks. Consider removing the self-destruct functionality unless it is absolutely required. If there is a valid use case, it is recommended to implement a multi-sig scheme so that multiple parties must approve the self-destruct action.
Exploit Scenario
The contract is self-destructed and re-initialized as a new contract. In this case, users lose all the data and values stored on the original contract.
Recommendations
Implement a multi-sig scheme so that multiple parties must approve the self-destruct action.
Results
Resolved in commits b3a22e085eac735371064a14e95e972ba721d078 and 743971fae48b905e18435f6370890a584387efea. The self-destruct function is removed and the major contracts are now pausable.
PieFi team implemented this feature so that in the event of an emergency they will be able to pause the contracts and prevent any state changes. Meanwhile, read operations will still be possible.
- No function to update the
SubDomainNode.maxRecords
Severity Low Source SubdomainNode.sol#L11; Status Acknowledged. Description
There is no function that can be used to update the variable
SubDomainNode.maxRecords
.
Exploit Scenario
N/A
Recommendations
Mark the variable as
immutable
or add a function to update the variable’s value.
Results
Acknowledged.
Reply from PieFi team:
“This is intentional. In our testing, we found that the Subdomain.sol contract can store more than 2000 subdomains before the contract runs out of space. We find this is an acceptable limitation.”
- Lack of event emission for critical operations.
Severity Low Source Hashgraph Name Protocol Status Resolved in commit b3a22e085eac735371064a14e95e972ba721d078. Description
Many of the HNS contract functions related to critical operations do not emit necessary events. Events are vital aids in monitoring contracts and detecting suspicious behaviors. Operations that perform critical operations should trigger events so that users and off-chain monitoring tools can account for important state changes.
Exploit Scenario
N/A
Recommendations
Please consider emitting events in functions that perform critical operations.
Results
Resolved in commit b3a22e085eac735371064a14e95e972ba721d078.
In this commit,
SetSLDInfo
,ExtendExpiry
,UpdateSLD
,AddSubdomain
,SetSubdomainInfo
,AddSubdomain
,TokenTransfer
seven events are added.
Informational
Informational
- No view function to fetch array length
Severity Informational Source SLDNode.sol#L10; SubdomainNode.sol#L8, L9; Status Acknowledged. Description
There is no view function to fetch the length of array
SLDNode.serials
,SubdomainNode.subdomainHashes
,SubdomainNode.name
.
Exploit Scenario
N/A
Recommendations
Add a
view
function to fetch the length of arrays.
Results
Acknowledged.
Reply from PieFi team:
“We don’t have a use case to be able to query for the array lengths.”
- Add view function to get array item by index
Severity Informational Source SLDNode.sol; TLDNode.sol; SubdomainNode.sol; Status Acknowledged. Description
A
view
function can be added to fetch array items by index.
Exploit Scenario
N/A
Recommendations
Add view functions to get array items by index.
Results
Acknowledged.
Reply from PieFi team:
“We don’t have a use case to fetch individual items in the arrays. They are mostly used for tracking purposes. We do, however, want to be able to fetch the entire array in the event we want to view all data in the Node.”
- Add view functions to retrieve valid SLD nodes
Severity Informational Source SLDNode.sol; TLDNode.sol; Status Resolved in commit b3a22e085eac735371064a14e95e972ba721d078. Description
SLD nodes contract still exists in array in TLD node contract after self-destructed. A view function to view all the nodes that are self-destructed can be added.
Exploit Scenario
N/A
Recommendations
A
view
function to view all the nodes that are self-destructed can be added.
Results
Resolved in commit b3a22e085eac735371064a14e95e972ba721d078.
- Access control on external view functions
Severity Informational Source SLDNode.sol#L50, L54; Status Resolved in commit b3a22e085eac735371064a14e95e972ba721d078. Description
The
view
functionsSLDNode.getMaxRecords()
andSLDNode.getNumRecords()
will revert if called by non-TLD owner. Access control on public view functions is unnecessary since everything on the blockchain is public and can be accessed by everyone.
Exploit Scenario
N/A
Recommendations
Suggest removing the access control if it is unnecessary.
Results
Resolved in commit b3a22e085eac735371064a14e95e972ba721d078.
Access Control Analysis
Access Control Analysis
- Owner of TLD node manager
The owner of TLDManager.sol is the deployer of this contract. The ownership cannot be renounced or transferred to others. The owner can:
- Register new TLD nodes or override any registered TLD nodes;
- Self-destruct TLDManager.sol.
- Owner of TLD node
The owner of TLDNode.sol is the deployer of this contract. The ownership cannot be renounced or transferred to others. The owner can:
- Register new SLD node records;
- Register expired SLD node records;
- Extend the expiry date of an SLD record;
- Add subdomain;
- Set subdomain info;
- Self-destruct TLDNode.sol;
- Self-destruct SLDNode.sol;
- Self-destruct SubdomainNode.sol.
Appendix I: Severity Categories
Appendix I: Severity Categories
Severity | Description |
---|---|
High | Issues that are highly exploitable security vulnerabilities. It may cause direct loss of funds / permanent freezing of funds. All high severity issues should be resolved. |
Medium | Issues that are only exploitable under some conditions or with some privileged access to the system. Users’ yields/rewards/information is at risk. All medium severity issues should be resolved unless there is a clear reason not to. |
Low | Issues that are low risk. Not fixing those issues will not result in the failure of the system. A fix on low severity issues is recommended but subject to the client's decisions. |
Informational | Issues that pose no risk to the system and are related to the security best practices. Not fixing those issues will not result in the failure of the system. A fix on informational issues or adoption of those security best practices-related suggestions is recommended but subject to clients’ decision. |
Appendix II: Status Categories
Appendix II: Status Categories
Status | Description |
---|---|
Unresolved | The issue is not acknowledged and not resolved. |
Partially Resolved | The issue has been partially resolved. |
Acknowledged | The Finding / Suggestion is acknowledged but not fixed / not implemented. |
Resolved | The issue has been sufficiently resolved. |
Disclaimer
Disclaimer
Verilog Solutions receives compensation from one or more clients for performing the smart contract and auditing analysis contained in these reports. The report created is solely for Clients and published with their consent. As such, the scope of our audit is limited to a review of code, and only the code we note as being within the scope of our audit detailed in this report. It is important to note that the Solidity code itself presents unique and unquantifiable risks since the Solidity language itself remains under current development and is subject to unknown risks and flaws. Our sole goal is to help reduce the attack vectors and the high level of variance associated with utilizing new and consistently changing technologies. Thus, Verilog Solutions in no way claims any guarantee of security or functionality of the technology we agree to analyze.
In addition, Verilog Solutions reports do not provide any indication of the technologies proprietors, business, business model, or legal compliance. As such, reports do not provide investment advice and should not be used to make decisions about investment or involvement with any particular project. Verilog Solutions has the right to distribute the Report through other means, including via Verilog Solutions publications and other distributions. Verilog Solutions makes the reports available to parties other than the Clients (i.e., “third parties”) – on its website in hopes that it can help the blockchain ecosystem develop technical best practices in this rapidly evolving area of innovation.