Smart Contract Audit

Naplozz
June 26, 2023

Summary

Vidma team has conducted a smart contract audit for the given codebase.

The contracts are in good condition. Based on the fixes provided by the Ammbr team and on the quality and security of the codebase provided, Vidma team can give a score of 95 to the audited smart contracts.

During the auditing process, the Vidma team has found a couple of informational issues, 7 issues with a low level of severity, 1 issue with a medium level of severity, and 3 issues with a critical level of severity.

Severity of the issue
Total found
Resolved
Unresolved
Critical
3 issues
3 issues
0 issues
High
3 issues
3 issues
0 issues
Medium
3 issues
3 issues
0 issues
Low
3 issues
3 issues
0 issues
Informational
3 issues
3 issues
0 issues
Low
3 issues
3 issues
0 issues

The contracts are in good condition. Based on the fixes provided by the Ammbr team and on the quality and security of the codebase provided, Vidma team can give a score of 95 to the audited smart contracts.

Based on the given findings, risk level, performance, and code style, Vidma team can grant the following overall score:

Please mind that this audit does not certify the definite reliability and security level of the contract. This document describes all vulnerabilities, typos, performance issues, and security issues found by Vidma auditing team. If the code is under development, we recommend run one more audit once the code is finalized.

Summary

Vidma is pleased to present this audit report outlining our assessment of code, smart contracts, and other important audit insights and suggestions for management, developers, and users.

The audited scope included token, vesting, and staking contracts. The protocol uses ERC2771Forwarder contract to operate on forward requests.

In the vesting contract, the tokens are not locked directly in the contract while the lock function is called so tokens will be locked as per admin when a user buys a subscription. Withdraw of vested tokens is only allowed for the Vester role, and includes some fee based on project performance and gas fee that is reduced from claimed amount. The fee can be transferred to the ecosystem pool by the contract admin.

During the audit process, the Vidma team found several issues, including those with high severity. A detailed summary and the current state are displayed in the table below.

Severity of the issue Issue severity
Critical
High
Medium
Low
Informational
Total
Severity of the issue Issue severity Total found Resolved Unresolved
Critical 0 issues 0 issues 0 issues
High 1 issue 1 issue 0 issues
Medium 0 issues 0 issues 0 issues
Low 0 issues 0 issues 0 issues
Informational 1 issue 1 issue 0 issues
Total 2 issues 2 issues 0 issues

After evaluating the findings in this report and the final state after fixes, the Vidma auditors can state that the contracts are fully operational and secure. Under the given circumstances, we set the following risk level:

High Confidence

To set the codebase quality mark, our auditors are evaluating the initial commit given for the scope of the audit and the last commit with the fixes. This approach helps us adequately and sequentially evaluate the quality of the code. Code style, optimization of the contracts, the number of issues, and risk level of the issues are all taken into consideration. The Vidma team has developed a transparent evaluation codebase quality system presented below.

Severity of the issue
Issue severity
Total found
Resolved
Critical
1
10
High
0.8
7
Medium
0.5
5
Low
0.2
0.5
Informational
0
0.1
Please note that the points are deducted out of 100 for each and every issue on the list of findings (according to the current status of the issue). Issues marked as “not valid” are not subject to point deduction.
Codebase quality:
98.90

Evaluating the initial commit and the last commit with the fixes, Vidma audit team set the following codebase quality mark.

Score
Based on the overall result of the audit and the state of the final reviewed commit, the Vidma audit team grants the following score:

98.90

In addition to manual check and static analysis, the auditing team has conducted a number of integrated autotests to ensure the given codebase has an adequate performance and security level. The test results and coverage can be found in the accompanying section of this audit report.

Please be aware that this audit does not certify the definitive reliability and security level of the contract. This document describes all vulnerabilities, typos, performance issues, and security issues found by the Vidma audit team.
If the code is still under development, we highly recommend running one more audit once the code is finalized.

Scope of work

Qoodo is a quality management and data tracking application utilizing the innovative technology of the blockchain to help businesses function more efficiently.

Within the scope of this audit, two independent auditors thoroughly investigated the given codebase and analyzed the overall security and performance of the smart contracts.

The audit was conducted from June 23, 2023 to June 26, 2023. The outcome is disclosed in this document.

The scope of work for the given audit consists of the following contracts:

  • EcoSystemPool;
  • NaplozzToken;
  • StakingNapTokens;
  • YearlyVesting.

The source code was taken from the following source:

https://github.com/NAPLOZZ/NAP-token-contracts

Initial commit submitted for the audit:

c1030a599b6435406bacf8e6bbd007d3edc59129

Last commit reviewed by the auditing team:

c67d25d5e42d65cf97f50b335bcae01f12a6a3fc

As a reference to the contracts logic, business concept, and the expected behavior of the codebase, the Naplozz team has provided the following documentation:

https://docs.naplozz.io/

Workflow of the auditing process

Vidma audit team uses the most sophisticated and contemporary methods and well-developed techniques to ensure contracts are free of vulnerabilities and security risks. The overall workflow consists of the following phases:

Phase 1: The research phase

Research

After the Audit kick-off, our security team conducts research on the contract’s logic and expected behavior of the audited contract.

Documentation reading

Vidma auditors do a deep dive into your tech documentation with the aim of discovering all the behavior patterns of your codebase and analyzing the potential audit and testing scenarios.

The outcome

At this point, the Vidma auditors are ready to kick off the process. We set the auditing strategies and methods and are prepared to conduct the first audit part.

Phase 2: Manual part of the audit

Manual check

During the manual phase of the audit, the Vidma team manually looks through the code in order to find any security issues, typos, or discrepancies with the logic of the contract. The initial commit as stated in the agreement is taken into consideration.

Static analysis check

Static analysis tools are used to find any other vulnerabilities in smart contracts that were missed after a manual check.

The outcome

An interim report with the list of issues.

Phase 3: Testing part of the audit

Integration tests

Within the testing part, Vidma auditors run integration tests using the Truffle or Hardhat testing framework. The test coverage and the test results are inserted in the accompanying section of this audit report.

The outcome

Second interim report with the list of new issues found during the testing part of the audit process.

Structure and organization of the findings

For simplicity in reviewing the findings in this report, Vidma auditors classify  the findings in accordance with the severity level of the issues. (from most critical to least critical).

All issues are marked as “Resolved” or “Unresolved”, depending on if they have been fixed by project team or not. The issues with “Not Relevant” status are left on the list of findings but are not eligible for the score points deduction.

The latest commit with the fixes reviewed by the auditors is indicated in the “Scope of Work” section of the report.

The Vidma team always provides a detailed description of the issues and recommendations on how to fix them.

Classification of found issues is graded according to 6 levels of severity described below:

Critical
The issue affects the contract in such a way that funds may be lost or allocated incorrectly, or the issue could result in a significant loss.
Example: Underflow/overflow, precisions, locked funds.
High
The issue significantly affects the ability of the contract to compile or operate. These are potential security or operational issues.
Example: Compilation errors, pausing/unpausing of some functionality, a random value, recursion, the logic that can use all gas from block (too many iterations in the loop), no limitations for locking period, cooldown, arithmetic errors which can cause underflow, etc.
Medium
The issue slightly impacts the contract’s ability to operate by slightly hindering its intended behavior.
Example: Absence of emergency withdrawal of funds, using assert for parameter sanitization.
Low
The issue doesn’t contain operational or security risks, but are more related to optimization of the codebase.
Example: Unused variables, inappropriate function visibility (public instead of external), useless importing of SCs, misuse or disuse of constant and immutable, absent indexing of parameters in events, absent events to track important state changes, absence of getters for important variables, usage of string as a key instead of a hash, etc.
Informational
Are classified as every point that increases onboarding time and code reading, as well as the issues which have no impact on the contract’s ability to operate.
Example: Code style, NatSpec, typos, license, refactoring, naming convention (or unclear naming), layout order, functions order, lack of any type of documentation.

Manual Report

Sensitive data is available in the repository

High  MH – 01 |  Resolved

There is the original .env file in the repository last commit. Passwords and private keys are exposed.

Recommendation:

Consider adding .env to the .gitignore so the private data won't be exposed by unauthorized users which can lead to the exploit.

Update natspec

Informational  MI – 01 |  Resolved

Constructor params are changed in the StakingNapTokens, NaplozzToken, EcoSystemPool and YearlyVesting contracts. But the natspec comments are not changed.

Recommendation:

Consider updating the natspec comments.

Test Results

To verify the security of  contracts and the performance, a number of integration tests were carried out using the Truffle testing framework.

In this section, we provide both tests written by Naplozz and tests written by Vidma auditors.

Naplozz Coverage – 92%

Vidma Coverage – 100%

Industry Standard – 95%

It is important to note that Vidma auditors do not modify, edit or add tests to the existing tests provided in the Naplozz repository. We write totally separate tests with code coverage of a minimum of 95% to meet the industry standards.

Tests written by Naplozz

Test Coverage

File
contracts\
EcoSystemPool.sol
NaplozzToken.sol
StakingNapTokens.sol
YearlyVesting.sol
All Files
File % Stmts % Branch % Funcs % Lines
contracts\ 92.00 92.16 87.50 94.89
EcoSystemPool.sol 83.33 100.00 80.00 85.71
NaplozzToken.sol 83.33 95.00 87.50 84.62
StakingNapTokens.sol 93.22 88.89 92.86 96.43
YearlyVesting.sol 95.65 95.00 80.00 96.97
All Files 92.00 92.16 87.50 94.89

Test Results

Contract: EcoSystemPool

  • should add token address
  • relay: should add token address(79ms)
  • should not allow address zero as token address(38ms)
  • should only allow owner to set token address
  • should transfer token to given address(69ms)
  • should not allow zero address
  • should only allow owner to transfer fund

Contract: NaplozzToken

  • should enabled anisniperdisabled variable
  • relay should revert if anisniperdisabled already set(47ms)
  • relay should enabled anisniperdisabled variable(40ms)
  • should revert if anisniperdisabled already set
  • should only allow default admin to call antisniperdisabled(73ms)
  • relay set anisniper contract address
  • should set anisniper contract address
  • should revert if anisniper contract address is zero
  • should only allow default admin to call setAntisnipeAddress(62ms)
  • should mint token to given address
  • should only allow minter to mint token(62ms)
  • should burn token from given address(56ms)
  • should not allow burner to burn token if there is no enough allownce(50ms)
  • should only allow burner to burn token(90ms)

Contract: StakingNapTokens

  • relay should fund the staking contract(112ms)
  • should not fund the staking contract if it has reached endblock
  • relay should not fund the staking contract if it has reached endblock(52ms)
  • should stake token(113ms)
  • relay should stake token(160ms)
  • should give out pending reward if user stake token in raw(157ms)
  • relay should give out pending reward if user stake token in raw(243ms)
  • should fail to stake if staking amount is zero(54ms)
  • relay should fail to stake if staking amount is zero(118ms)
  • should fail to stake if endblock is reached(67ms)
  • should fail to stake if contract is not funded
  • should harvest user reward(262ms)
  • should only harvest if pending reward is not zero(141ms)
  • should withdraw user staked amount in emergency(153ms)
  • should only allow to emergency withdraw if staking is paused(116ms)
  • should not withdraw user staked amount in emergency if user has not staked token(55ms)
  • should withdraw user given amount of staked token and reward user(pending reward)(171ms)
  • should not allow to withdraw amount more than user has staked(98ms)
  • should not allow to withdraw zero amount(90ms)
  • should pause the contract
  • should only allow owner to pause the contract
  • should only allow owner to pause the contract if it is not alredy paused
  • should unpause the contract
  • should only allow owner to unpause the contract
  • should only allow owner to unpause the contract if it is paused
  • should calculate pending reward(89ms)
  • should return zero for calculatePendingRewards if token is not staked(38ms)
  • should not update accTokenPerShare if tokenreward is zero(107ms)
  • should update rewardperblock and endblock(106ms)
  • should only allow owner to update rewardperblock and endblock(96ms)
  • should not allow to update rewardperblock if staking has not started(43ms)
  • should not allow to update rewardperblock if staking has ended(93ms)
  • should not allow to update rewardperblock if newrewardperblock is zero(95ms)
  • should not allow to update rewardperblock if newrewardperblock is less than remaining(106ms)

Contract: YearlyVesting

  • should not deploy if token address is zero
  • should lock token into contract(82ms)
  • should allow only owner to lock token into contract
  • should revert if receiver address is zero
  • should revert if token already staked(49ms)
  • should withdraw token after 1 year(91ms)
  • should withdraw token after 1.8 year(83ms)
  • should withdraw token after 2 years(86ms)
  • should withdraw token after 3 years(83ms)
  • should withdraw token after 4 years(88ms)
  • should only allow receiver to withdraw fund(45ms)
  • should not allow to withdraw fund if locking period is not end(49ms)
  • should not allow to withdraw fund if it is already claimed once(150ms)
68 passing(21s)

Tests written by Vidma auditors

Test Coverage

File
contracts\
EcoSystemPool.sol
NaplozzToken.sol
StakingNapTokens.sol
YearlyVesting.sol
All Files
File % Stmts % Branch % Funcs % Lines
contracts\ 100.00 99.02 100.00 100.00
EcoSystemPool.sol 100.00 100.00 100.00 100.00
NaplozzToken.sol 100.00 100.00 100.00 100.00
StakingNapTokens.sol 100.00 98.15 100.00 100.00
YearlyVesting.sol 100.00 100.00 100.00 100.00
All Files 100.00 99.02 100.00 100.00

Test Results

Contract: EcoSystemPool

  • Should set token address in the pool correct
  • Should not add zero token address to the pool
  • Should transfer tokens from the pool correct(66ms)
  • Should not transfer tokens from the pool to the zero address
  • Should not set token address in the pool if the caller is not owner
  • Should not transfer tokens from the pool if the caller is not owner
  • _msg.data
    • Should return the data of the transaction correct

Contract: NaplozzToken

  • Should set the default admin role correct
  • Should set the minter role correct
  • check basic init
    • has a name
    • has a symbol
    • has 18 decimals
  • mint
    • Should mint token correct
    • Should not mint token if the caller is not minter
  • burn
    • Should burn token correct(62ms)
    • Should not burn token if the caller is not burner
    • Should not burn tokens if there is not enough allowance
  • setAntisnipeDisable
    • Should set antisnipeDisable correct
    • Should not set antisnipeDisable if the caller is not the default admin
    • Should not set antisnipeDisable twice
    • Should set antisnipe contract correct(40ms)
    • Should not set antisnipe contract zero address
    • Should not set antisnipe contract if the caller is not the default admin
  • ERC20 behavior
    • Should transfer correct(45ms)
    • Should not transfer if the caller has not enough balance
    • should not transfer to zero address(38ms)
    • Should transferFrom tokens correct(81ms)
    • Should not transferFrom tokens if the caller has not enough allowance(45ms)
    • Should not transferFrom to zero address
    • Should approve tokens correct
    • ansnipe is disable
      • Should transfer correct(52ms)
  • _msg.data
    • Should return the data of the transaction correct

Contract: StakingNapTokens

  • initialization
    • Should set staked token address in the staking contract correct
    • Should set reward token address in the staking contract correct(42ms)
    • Should set reward per block in the staking contract correct
    • Should set start block in the staking contract correct
    • Should set end block in the staking contract correct
    • Should set last reward block in the staking contract correct
  • fund
    • Should fund the staking contract with reward token correct(91ms)
    • Should not fund if the end block is reached(54ms)
  • deposit
    • Should deposit staked token to the staking contract correct(185ms)
    • Should not deposit if the end block is reached and staking is ended(86ms)
    • Should not deposit if the amount is zero
    • Should not deposit if the staking is not funded
    • Should deposit twice correct(184ms)
  • harvest
    • Should harvest reward token correct(185ms)
    • Should not harvest id there is no pending reward(124ms)
  • withdraw
    • Should withdraw before staking ends correct (1 user)(170ms)
    • Should withdraw after staking ends correct (2 users)(319ms)
    • Should withdraw correct (3 users)(410ms)
    • Should not withdraw if the requested amount is 0(138ms)
    • Should not withdraw if not deposited(75ms)
    • Should withdraw correct if there are no rewards(166ms)
  • emergencyWithdraw
    • Should pause contract correctly
    • Should unpause contract correctly(44ms)
    • Should not pause contract if not owner
    • Should not pause when already paused(49ms)
    • Should not unpause when not paused
    • Should not unpause when not owner(43ms)
    • Should emergency withdraw when contract is paused correctly(183ms)
    • Should not emergency withdraw when contract is not paused(119ms)
    • Should not emergency withdraw if not deposited(97ms)
    • Should not emergency withdraw twice(192ms)
  • updateRewardPerBlock
    • Should update reward per block(82ms)
    • Should not update reward per block if not owner
    • Should not update reward per block if staking is not started
    • Should not update reward per block if staking is finished(67ms)
    • Should not update reward per block if zero(89ms)
    • Should not update reward per block if greater than remaining rewards(98ms)
  • _msg.data
    • Should return the data of the transaction correct

Contract: YearlyVesting

  • initialization
    • Should set token address in the vesting contract correct
    • Should not set token address as zero address while deploy
  • lock
    • Should lock tokens to the vesting contract correct(57ms)
    • Should not lock tokens to the vesting contract if the user is zero address
    • Should not lock tokens to the vesting contract for the same user twice(63ms)
    • Should not lock tokens to the vesting contract if the caller is not the owner
  • withdraw
    • Should not withdraw any tokens from the vesting before 1 year passed(76ms)
    • Should withdraw tokens from the vesting contract after 1 year correct(119ms)
    • Should withdraw tokens from the vesting contract after 2 years correct(137ms)
    • Should withdraw tokens from the vesting contract after 2.5 years correct(210ms)
    • Should withdraw tokens from the vesting contract after 3 years correct(180ms)
    • Should withdraw tokens from the vesting contract after 3.5 years correct(210ms)
    • Should withdraw tokens from the vesting contract after 4 years correct(205ms)
    • Should not withdraw tokens if everything is claimed already(218ms)
    • Should not withdraw tokens if the user is not the receiver
  • _msg.data
    • Should return the data of the transaction correct
86 passing(29s)

We are delighted to have a chance to work with the Naplozz team and contribute to your company's success by reviewing and certifying the security of your smart contracts.

The statements made in this document should be interpreted neither as investment or legal advice, nor should its authors be held accountable for decisions made based on this document.

Vidma is a security audit company helping crypto companies ensure their code and products operate safely and as intended, enabling founders to sleep soundly at night. We specialize in auditing DeFi protocols, layer one protocols, and marketplace solutions. Our team consists of experienced and internationally trained specialists. Our company is based in Ukraine, known for its strong engineering, cryptography, and cybersecurity culture.
4