Halborn Logo

Saferoot Contracts - Staging Labs


Prepared by:

Halborn Logo

HALBORN

Last Updated 04/25/2024

Date of Engagement by: July 12th, 2023 - July 21st, 2023

Summary

100% of all REPORTED Findings have been addressed

All findings

13

Critical

0

High

0

Medium

0

Low

3

Informational

10


1. INTRODUCTION

Saferoot is designed to provide additional safety features for the users of ERC-20, ERC-721, and ERC-1155 tokens. It provides a safety mechanism in case of a mistake, hack, or scam by transferring the users' tokens from their wallet to their backup address before the transaction that triggered the safeguard executes.

\client engaged Halborn to conduct a security assessment on their smart contracts beginning on 2023-07-12 and ending on 2023-07-21. The security assessment was scoped to the smart contracts provided in the Staging-Labs/Saferoot-Contract GitHub repository. Commit hashes and further details can be found in the Scope section of this report.

2. ASSESSMENT SUMMARY

Halborn was provided one week for the engagement and assigned a team of one full-time security engineer to review the security of the smart contracts in scope. The security team consists of a blockchain and smart contract security experts with advanced penetration testing and smart contract hacking skills, and deep knowledge of multiple blockchain protocols.

The purpose of the assessment is to:

    • Identify potential security issues within the smart contracts.

    • Ensure that smart contract functionality operates as intended.

In summary, Halborn identified some improvements to reduce the likelihood and impact of risks that were mostly addressed by Staging Labs.

3. TEST APPROACH & METHODOLOGY

Halborn performed a combination of manual and automated security testing to balance efficiency, timeliness, practicality, and accuracy in regard to the scope of this assessment. While manual testing is recommended to uncover flaws in logic, process, and implementation; automated testing techniques help enhance coverage of the code and can quickly identify items that do not follow the security best practices. The following phases and associated tools were used during the assessment:

    • Research into architecture and purpose

    • Smart contract manual code review and walkthrough

    • Graphing out functionality and contract logic/connectivity/functions (solgraph)

    • Manual assessment of use and safety for the critical Solidity variables and functions in scope to identify any arithmetic related vulnerability classes

    • Manual testing by custom scripts

    • Scanning of solidity files for vulnerabilities, security hot-spots or bugs. (MythX)

    • Static Analysis of security for scoped contract, and imported functions. (Slither)

    • Testnet deployment (Foundry, Brownie)

4. SCOPE

    1. Saferoot Contracts

    2. Repository: Staging-Labs/Saferoot-Contract

    3. Commit ID: 834455599dacda269ed222182c3576bf37d70038

    4. Smart contracts in scope:

      • contracts/ContractRegistry.sol

      • contracts/ErrorReporter.sol

      • contracts/Saferoot.sol

      • contracts/SaferootFactory.sol

    5. Final fix commit ID: 0884050

    6. contracts/ContractRegistry.sol

    7. contracts/ErrorReporter.sol

    8. contracts/Saferoot.sol

    9. contracts/SaferootFactory.sol

Out-of-scope:

    • third-party libraries and dependencies

    • economic attacks

5. RISK METHODOLOGY

Every vulnerability and issue observed by Halborn is ranked based on two sets of Metrics and a Severity Coefficient. This system is inspired by the industry standard Common Vulnerability Scoring System.
The two Metric sets are: Exploitability and Impact. Exploitability captures the ease and technical means by which vulnerabilities can be exploited and Impact describes the consequences of a successful exploit.
The Severity Coefficients is designed to further refine the accuracy of the ranking with two factors: Reversibility and Scope. These capture the impact of the vulnerability on the environment as well as the number of users and smart contracts affected.
The final score is a value between 0-10 rounded up to 1 decimal place and 10 corresponding to the highest security risk. This provides an objective and accurate rating of the severity of security vulnerabilities in smart contracts.
The system is designed to assist in identifying and prioritizing vulnerabilities based on their level of risk to address the most critical issues in a timely manner.

5.1 EXPLOITABILITY

Attack Origin (AO):
Captures whether the attack requires compromising a specific account.
Attack Cost (AC):
Captures the cost of exploiting the vulnerability incurred by the attacker relative to sending a single transaction on the relevant blockchain. Includes but is not limited to financial and computational cost.
Attack Complexity (AX):
Describes the conditions beyond the attacker’s control that must exist in order to exploit the vulnerability. Includes but is not limited to macro situation, available third-party liquidity and regulatory challenges.
Metrics:
EXPLOITABILIY METRIC (mem_e)METRIC VALUENUMERICAL VALUE
Attack Origin (AO)Arbitrary (AO:A)
Specific (AO:S)
1
0.2
Attack Cost (AC)Low (AC:L)
Medium (AC:M)
High (AC:H)
1
0.67
0.33
Attack Complexity (AX)Low (AX:L)
Medium (AX:M)
High (AX:H)
1
0.67
0.33
Exploitability EE is calculated using the following formula:

E=meE = \prod m_e

5.2 IMPACT

Confidentiality (C):
Measures the impact to the confidentiality of the information resources managed by the contract due to a successfully exploited vulnerability. Confidentiality refers to limiting access to authorized users only.
Integrity (I):
Measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of data stored and/or processed on-chain. Integrity impact directly affecting Deposit or Yield records is excluded.
Availability (A):
Measures the impact to the availability of the impacted component resulting from a successfully exploited vulnerability. This metric refers to smart contract features and functionality, not state. Availability impact directly affecting Deposit or Yield is excluded.
Deposit (D):
Measures the impact to the deposits made to the contract by either users or owners.
Yield (Y):
Measures the impact to the yield generated by the contract for either users or owners.
Metrics:
IMPACT METRIC (mIm_I)METRIC VALUENUMERICAL VALUE
Confidentiality (C)None (I:N)
Low (I:L)
Medium (I:M)
High (I:H)
Critical (I:C)
0
0.25
0.5
0.75
1
Integrity (I)None (I:N)
Low (I:L)
Medium (I:M)
High (I:H)
Critical (I:C)
0
0.25
0.5
0.75
1
Availability (A)None (A:N)
Low (A:L)
Medium (A:M)
High (A:H)
Critical (A:C)
0
0.25
0.5
0.75
1
Deposit (D)None (D:N)
Low (D:L)
Medium (D:M)
High (D:H)
Critical (D:C)
0
0.25
0.5
0.75
1
Yield (Y)None (Y:N)
Low (Y:L)
Medium (Y:M)
High (Y:H)
Critical (Y:C)
0
0.25
0.5
0.75
1
Impact II is calculated using the following formula:

I=max(mI)+mImax(mI)4I = max(m_I) + \frac{\sum{m_I} - max(m_I)}{4}

5.3 SEVERITY COEFFICIENT

Reversibility (R):
Describes the share of the exploited vulnerability effects that can be reversed. For upgradeable contracts, assume the contract private key is available.
Scope (S):
Captures whether a vulnerability in one vulnerable contract impacts resources in other contracts.
Metrics:
SEVERITY COEFFICIENT (CC)COEFFICIENT VALUENUMERICAL VALUE
Reversibility (rr)None (R:N)
Partial (R:P)
Full (R:F)
1
0.5
0.25
Scope (ss)Changed (S:C)
Unchanged (S:U)
1.25
1
Severity Coefficient CC is obtained by the following product:

C=rsC = rs

The Vulnerability Severity Score SS is obtained by:

S=min(10,EIC10)S = min(10, EIC * 10)

The score is rounded up to 1 decimal places.
SeverityScore Value Range
Critical9 - 10
High7 - 8.9
Medium4.5 - 6.9
Low2 - 4.4
Informational0 - 1.9

6. SCOPE

Out-of-Scope: New features/implementations after the remediation commit IDs.

7. Assessment Summary & Findings Overview

Critical

0

High

0

Medium

0

Low

3

Informational

10

Security analysisRisk levelRemediation Date
MISSING ZERO ADDRESS CHECKSLowSolved - 08/07/2023
REGISTRY CANNOT BE RE-ENABLEDLowSolved - 08/02/2023
REGISTRY CANNOT BE CHANGEDLowSolved - 08/02/2023
LACK OF SAFEGUARD DATA VALIDATIONInformationalSolved - 08/08/2023
LACK OF DISABLEINITIALIZERS IN THE IMPLEMENTATION CONTRACTInformationalSolved - 08/04/2023
ARBITRARY AMOUNT OF SAFEGUARDS CAN BE ADDEDInformationalAcknowledged - 08/23/2023
INCOMPATIBILITY WITH TOKENS NOT FOLLOWING THE STANDARDSInformationalAcknowledged - 08/23/2023
MULTIPLE SAFEGUARDS CAN BE ADDED TO THE SAME ASSETInformationalSolved - 08/23/2023
ITERATING OVER A DYNAMIC ARRAYInformationalAcknowledged - 08/18/2023
MISTAKENLY SENT TOKENS AND ETHER CANNOT BE RECOVERED FROM THE CONTRACTSInformationalSolved - 08/08/2023
FOR LOOPS CAN BE GAS OPTIMIZEDInformationalSolved - 08/08/2023
UNNECESSARY VALIDATIONInformationalSolved - 08/07/2023
NOT ALL EVM COMPATIBLE CHAIN SUPPORTS SOLIDITY 0.8.20InformationalAcknowledged - 08/18/2023

8. Findings & Tech Details

8.1 MISSING ZERO ADDRESS CHECKS

// Low

Description

The backup state variable is used to store the address where the user's tokens are transferred if safeguards are initiated. However, it was identified that this variable lacks zero address validation when configured. Setting an invalid backup address results in loss of funds.

The service state variable is used to store the address of the account that is authorized to initiate safeguards. This variable also lacks zero address validation. Configuring an invalid address prevents the Saferoot contract from initiating safeguards.

The contractRegistry state variable points to the contract's registry used for token verification. If it is set to zero when the registry is enabled, no safeguards can be added.

The user state variable points to the contract's user address. If set incorrectly, the contract's functions are inaccessible.

Code Location

contracts/Saferoot.sol

function initialize(
    address _service,
    address _user,
    address _backup,
    address _contractRegistry,
    bool _registryEnabled
) public initializer {
    user = _user;
    backup = _backup;
    service = _service;
    contractRegistry = _contractRegistry;
    registryEnabled = _registryEnabled;
    _grantRole(SERVICE_ROLE, _service);
    _grantRole(USER_ROLE, _user);

    emit SaferootCreated(_user, _service);
}

contracts/Saferoot.sol

function setBackupWallet(address _backup) external onlyUser {
    backup = _backup;
    emit BackupUpdated(_backup);
}
BVSS
Recommendation

SOLVED: The \client team solved the issue in commit 9e26e35 by adding zero address checks.

8.2 REGISTRY CANNOT BE RE-ENABLED

// Low

Description

The ContractRegistry contract is responsible for storing the addresses of the token contracts that are Saferoot verified. If this contract is disabled in the Saferoot contract, it can no longer be re-enabled. As a result, users could no longer use it to verify the token contracts when adding safeguards.

Code Location

If the registry is enabled in the Saferoot contract, it is used to verify the token contracts when adding safeguards:

contracts/Saferoot.sol

    if (
        registryEnabled &&
        !registry.isContractSupported(incomingSafeguard.contractAddress)
    ) {
        revert InvalidContractAddress();
    }

However, there is no enableRegistry function implemented in the Saferoot contract. The user can only disable the registry:

contracts/Saferoot.sol

    function disableRegistry() external onlyUser {
        registryEnabled = false;
        emit RegistryFlagUpdated(false);
    }
BVSS
Recommendation

SOLVED: The \client team concluded that the contract registry was unnecessary and removed it from the protocol in commit 5166c1d.

8.3 REGISTRY CANNOT BE CHANGED

// Low

Description

The ContractRegistry contract is responsible for storing the addresses of the contracts that are Saferoot verified. Users may wish to use a different implementation, but once the Saferoot contract is initialized, it is no longer possible to update the registry address in it.

Code Location

contracts/Saferoot.sol

    function initialize(
        address _service,
        address _user,
        address _backup,
        address _contractRegistry,
        bool _registryEnabled
    ) public initializer {
        user = _user;
        backup = _backup;
        service = _service;
        contractRegistry = _contractRegistry;
        registryEnabled = _registryEnabled;
        _grantRole(SERVICE_ROLE, _service);
        _grantRole(USER_ROLE, _user);

        emit SaferootCreated(_user, _service);
    }
BVSS
Recommendation

SOLVED: The \client team concluded that the contract registry was unnecessary and removed it from the protocol in commit 5166c1d.

8.4 LACK OF SAFEGUARD DATA VALIDATION

// Informational

Description

The safeguards are used to transfer the tokens from the user to the backup wallet address if they are initiated. It was identified that users can create safeguards with parameters that are not related to their token type. For example, it is possible to create an ERC20 token safeguard with a non-zero tokenId parameter. Using an invalid parameter indicates that the user may have accidentally switched the order of the values. Reverting these function makes it easier to detect such errors.

Code Location

The SafeguardEntry and SafeguardEditEntry structs are used in the addSafeguard and editSafeguard functions:

contracts/Saferoot.sol

    struct SafeguardEntry {
        TokenType tokenType;
        address contractAddress;
        uint256 amount;
        uint256 tokenId;
    }

contracts/Saferoot.sol

    struct SafeguardEditEntry {
        bytes32 key;
        uint256 newTokenId;
        uint256 newAmount;
    }

For example, the tokenId parameter is not checked in the ERC20 branch of the addSafeguard function:

contracts/Saferoot.sol

            SafeguardEntry memory incomingSafeguard = _ercEntries[index];
            if (incomingSafeguard.contractAddress == address(0)) {
                revert ZeroAddress();
            }

            // If registry is enabled and the contract is a safe + supported address
            if (
                registryEnabled &&
                !registry.isContractSupported(incomingSafeguard.contractAddress)
            ) {
                revert InvalidContractAddress();
            }

            bytes32 key = encodeKey(currentKey, incomingSafeguard.tokenType);
            if (incomingSafeguard.tokenType == TokenType.ERC20) {
                ERC20SafeguardInfo storage safeguard = erc20Safeguards[key];
                if (safeguard.contractAddress == address(0)) {
                    safeguard.contractAddress = incomingSafeguard
                        .contractAddress;
                    safeguard.amount = incomingSafeguard.amount;
                    emit ERC20SafeguardAdded(key);
                    unchecked {
                        ++currentKey;
                    }
                }
            }
BVSS
Recommendation

SOLVED: The \client team solved the issue in commits 6562223 and bbe3474 by reverting the related functions if the safeguards contain inappropriate values. The editSafeguard function was removed from the contract.

8.5 LACK OF DISABLEINITIALIZERS IN THE IMPLEMENTATION CONTRACT

// Informational

Description

The Saferoot contract uses the Initializable module from OpenZeppelin, and the implementations of this contract are not marked as initialized in the constructor. An uninitialized instance can be initialized by anyone to take over the contract. Even if it does not affect the instances deployed by the SaferootFactory, it is still a good practice to prevent the initialization of the implementation contracts to avoid misuse. In the latest versions, this is done by calling the _disableInitializers function in the constructor.

BVSS
Recommendation

SOLVED: The \client team solved the issue in commit d1df49e by including a constructor to automatically mark the contracts as initialized.

8.6 ARBITRARY AMOUNT OF SAFEGUARDS CAN BE ADDED

// Informational

Description

It was identified that there is no limit in the Saferoot contract on how many safeguards can be added by the user. Adding too many safeguards may prevent the service user to efficiently monitoring the system and call safeguards in time.

Note that the off-chain backend system was outside this security assessment's scope.

BVSS
Recommendation

ACKNOWLEDGED: The \client team acknowledged this finding and will perform tests to identify the limitations of the service and manage the number of active safeguards off-chain.

8.7 INCOMPATIBILITY WITH TOKENS NOT FOLLOWING THE STANDARDS

// Informational

Description

It was identified that the Saferoot contract may not be compatible with tokens that do not follow the ERC standards if these tokens do not implement the functions (e.g., getApproved, safeTransferFrom) that the Saferoot contract uses to verify permissions for token transfers or transfer tokens to the backup address (e.g., CryptoKitties and CryptoPunks NFTs).

BVSS
Recommendation

ACKNOWLEDGED: The \client team acknowledged this finding. They are going to create an off-chain database with the supported tokens, and they will notify the users about these limitations.

8.8 MULTIPLE SAFEGUARDS CAN BE ADDED TO THE SAME ASSET

// Informational

Description

It was identified that multiple safeguards can be added to the same asset in the Saferoot contract. Adding multiple safeguards for the same asset may prevent the backend systems from correctly identifying which safeguards should be called.

Note that the backend systems were outside this security assessment's scope.

BVSS
Recommendation

SOLVED: The \client team solved the issue in commit 837c806 by modifying the design of the Saferoot contract.

8.9 ITERATING OVER A DYNAMIC ARRAY

// Informational

Description

The initiateSafeguard function transfers the tokens from the user's wallet to the backup address based on the added safeguards. The keys of the safeguards to use are given in the function's _safeguardKeys array parameter. The function iterates through these keys and gets the data of the safeguards from the associated mappings, transferring the specified tokens from the user to the backup address. However, this involves looping over multiple array items, querying the required data, calling external contracts, and emitting events.

The execution of these actions requires a certain amount of gas based on how much computation is needed to complete them. Adding too many keys to the _safeguardKeys parameter may max out the gas limit, reverting the initiateSafeguard function, which prevents transferring the user's tokens in time.

Code Location

The initiateSafeguard function is looping over its dynamic array parameter:

contracts/Saferoot.sol

    function initiateSafeguard(bytes32[] calldata _safeguardKeys)
        external
        payable
        onlyService
        nonReentrant
    {
        for (uint256 index = 0; index < _safeguardKeys.length; ++index) {
            bytes32 key = _safeguardKeys[index];
            TokenType tokenType = decodeKeyTokenType(key);

            if (tokenType == TokenType.ERC20) {
                ERC20SafeguardInfo memory safeguard = erc20Safeguards[key];
                address contractAddress = safeguard.contractAddress;

                if (contractAddress != address(0)) {
                    // Transfer token
                    if (_transfer20(key, contractAddress, safeguard.amount)) {
                        emit SafeguardInitiated(key);
                    }
                    // If the contract address is already set, then skip
                    continue;
                }
            }
BVSS
Recommendation

ACKNOWLEDGED: The \client team acknowledged this finding.

8.10 MISTAKENLY SENT TOKENS AND ETHER CANNOT BE RECOVERED FROM THE CONTRACTS

// Informational

Description

It was identified that the Saferoot, SaferootFactory, and ContractRegistry contracts are missing functions to sweep/recover accidental ERC20 token and Ether transfers. Mistakenly sent tokens and Ether are locked in the contracts indefinitely.

BVSS
Recommendation

SOLVED: The \client team solved the issue in commit 910d794 by adding a function to enable the user to recover accidental ERC20 token transfers and removing the payable functions to prevent accidental Ether transfers. Note that only the user can withdraw accidental token transfers from the Saferoot contract.

8.11 FOR LOOPS CAN BE GAS OPTIMIZED

// Informational

Description

It was identified that the for loops employed in the contracts can be gas optimized by the following principles:

  • Unnecessary reading of the array length on each iteration wastes gas.

  • A postfix (e.g. i++) operator was used to increment the i variables. It is known that, in loops, using prefix operators (e.g. ++i) costs less gas per iteration than postfix operators. It is also possible to further optimize loops by using unchecked loop index incrementing and decrementing.

Note that view or pure functions only cost gas if they are called from on-chain.

Code Location

contracts/ContractRegistry.sol

  • Line 52: for (uint256 i = 0; i < _contracts.length; i++) {

contracts/Saferoot.sol

  • Line 249: for (uint256 index = 0; index < _safeguardKeys.length; ++index) {
  • Line 321: for (uint256 index; index < _ercEntries.length; ++index) {
  • Line 392: for (uint256 index = 0; index < _ercEditEntries.length; ++index) {

The original and the optimized gas cost of the updateSupportedContracts function were compared to measure its gas efficiency:

Original: 162236 gas_orig.png

Optimized: 161833 gas_optimized.png

Difference: 403

Score
Recommendation

SOLVED: The \client team solved the issue in commit 0914a6b by applying the above recommendations.

8.12 UNNECESSARY VALIDATION

// Informational

Description

It was identified that the addSafeguard function in the Saferoot contract employs unnecessary validation to check if the currentKey is already used or not. However, because the currentKey is increased every time a safeguard is added, this condition is always true.

Code Location

contracts/Saferoot.sol

    bytes32 key = encodeKey(currentKey, incomingSafeguard.tokenType);
    if (incomingSafeguard.tokenType == TokenType.ERC20) {
        ERC20SafeguardInfo storage safeguard = erc20Safeguards[key];
        if (safeguard.contractAddress == address(0)) {
            safeguard.contractAddress = incomingSafeguard
                .contractAddress;
            safeguard.amount = incomingSafeguard.amount;
            emit ERC20SafeguardAdded(key);
            unchecked {
                ++currentKey;
            }
        }
    } else if (incomingSafeguard.tokenType == TokenType.ERC721) {
        ERC721SafeguardInfo storage safeguard = erc721Safeguards[key];
        if (safeguard.contractAddress == address(0)) {
            safeguard.contractAddress = incomingSafeguard
                .contractAddress;
            safeguard.tokenId = incomingSafeguard.tokenId;
            emit ERC721SafeguardAdded(key);
            unchecked {
                ++currentKey;
            }
        }
    } else if (incomingSafeguard.tokenType == TokenType.ERC1155) {
        ERC1155SafeguardInfo storage safeguard = erc1155Safeguards[key];
        if (safeguard.contractAddress == address(0)) {
            safeguard.contractAddress = incomingSafeguard
                .contractAddress;
            safeguard.tokenId = incomingSafeguard.tokenId;
            safeguard.amount = incomingSafeguard.amount;
            emit ERC1155SafeguardAdded(key);
            unchecked {
                ++currentKey;
            }
        }
    }
Score
Recommendation

SOLVED: The \client team solved the issue in commit bc0e505 by removing the unnecessary checks from the addSafeguard function.

8.13 NOT ALL EVM COMPATIBLE CHAIN SUPPORTS SOLIDITY 0.8.20

// Informational

Description

It was identified that the contracts are using Solidity version 0.8.20 with its default Shanghai EVM version. The Shanghai fork introduced the PUSH0 opcode and was only supported on Mainnet, Goerli and Sepolia at the time of the assessment.

BVSS
Recommendation

ACKNOWLEDGED: The \client team acknowledged this finding. The \client team will adjust the EVM version when deploying to new ecosystems.

9. Review Notes

In the manual testing phase, the following scenarios were simulated. The scenarios listed below were selected based on the severity of the vulnerabilities Halborn was testing the program for.

ACCESS CONTROL AND ROLE MANAGEMENT

Description

Proper access control on privileged functions was tested. All functions were reviewed to ensure that no sensitive functionality was left unprivileged.

Results

  • Only the configured user with the USER_ROLE can add or edit safeguards, modify the backup wallet address or disable the registry in the Saferoot contract. This role is configured during initialization, and it is not possible to change it or assign it to any other users afterward.
  • Only the configured service account with the SERVICE_ROLE can initiate safeguards. This role is configured during initialization, and it is not possible to change it or assign it to any other users afterward.
  • Only the contract's deployer can edit the supported contract list in the ContractRegistry contract.
  • Anyone can use the SaferootFactory contract to create Saferoot contracts.

CONTRACT FUNCTIONALITY

Description

It was tested that the smart contract functionalities operate as intended.

Results

  • The encodeKey, decodeKeyTokenType and decodeKeyID functions used in the Saferoot contract are working as intended.
  • After initiating a safeguard by the service, the associated tokens are transferred from the user to the backup address. The Saferoot contract cannot transfer the assets to any other address.
  • If the registry is disabled, the user no longer able to enable it.
  • It is not possible to change the registry address.
  • It is possible to add multiple safeguards for the same asset.

DEPLOYMENT

Description

It was tested that the deployments of the Saferoot contracts with the SaferootFactory contract operate as intended.

Results

  • All contracts were deployed successfully, and the properties of the Saferoot contracts were configured properly.
  • The Saferoot contracts were deployed and initialized in the same transaction, preventing any malicious user to front run the initialize transaction.

10. Automated Testing

STATIC ANALYSIS REPORT

Description

Halborn used automated testing techniques to enhance the coverage of certain areas of the smart contracts in scope. Among the tools used was Slither, a Solidity static analysis framework. After Halborn verified the smart contracts in the repository and was able to compile them correctly into their ABIs and binary format, Slither was run against the contracts. This tool can statically verify mathematical relationships between Solidity variables to detect invalid or inconsistent usage of the contracts' APIs across the entire code-base.

Results

contracts/Saferoot.sol \input{slither/Saferoot}

contracts/SaferootFactory.sol \input{slither/SaferootFactory}

contracts/ContractRegistry.sol Slither did not identify any vulnerabilities in the contract.

contracts/ErrorReporter.sol Slither did not identify any vulnerabilities in the contract.

The findings obtained as a result of the Slither scan were reviewed. The medium-risk and reentrancy vulnerabilities were not included in the report because they were determined false positives.

AUTOMATED SECURITY SCAN

Description

Halborn used automated security scanners to assist with detection of well-known security issues and to identify low-hanging fruits on the targets for this engagement. Among the tools used was MythX, a security analysis service for Ethereum smart contracts. MythX performed a scan on the smart contracts and sent the compiled results to the analyzers in order to locate any vulnerabilities.

Results

contracts/Saferoot.sol

contracts/SaferootFactory.sol

contracts/ErrorReporter.sol

contracts/ContractRegistry.sol

The findings obtained as a result of the MythX scan were examined, and they were not included in the report because they were determined false positives.

Halborn strongly recommends conducting a follow-up assessment of the project either within six months or immediately following any material changes to the codebase, whichever comes first. This approach is crucial for maintaining the project’s integrity and addressing potential vulnerabilities introduced by code modifications.