Vidma team has conducted a smart contract audit for the given codebase.
We made deep auditing of the codebase provided and can confirm that the contact is in good condition.
During the auditing process, the Vidma team has found several issues, including issues with critical severity. A detailed summary of the issues and their current state is displayed in the table below.
Evaluating the findings, we can assure that the contract is safe to use and all the issues found are performed only by certain conditions and cases. Under the given circumstances we can set the following risk level:
Vidma auditors are evaluating the initial commit given for the scope of the audit and the last commit with the fixes. Hence, it helps to adequately evaluate the development quality. Code style, optimization of the contracts, amount, and risk level of the issues are taken into consideration. The Vidma team has developed the transparent scoring system presented below.
Based on the given findings, risk level, performance, and code style, Vidma team can grant the following overall score:
Vidma auditing team has conducted a bunch of integrated autotests to ensure that the given codebase has decent performance and security levels. The test results and the coverage can be found in the accompanying section of this audit report.
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.
POP Network is a user-friendly ecosystem of blockchain and AI applications built to power the streaming economy. Their vision is a universal system for turning attention into real-world goods and services.
Within the scope of this audit, two independent auditors deeply investigated the given codebase and analyzed the overall security and performance of smart contracts.
The debrief took place from March 7th to 16th, 2022 and the final results are present in this document.
Vidma auditing team has made a review of the following contract:
The source code was taken from the following source(zip archive) :
https://drive.google.com/file/d/13I7LoIMIK6JTLg_OQnh1T6Ap_9XA4ji_/view
Last commit:
256a5d40fb42b03912bf3a0386713f363e8bc4ae
To conduct a more detailed audit, POP Network has provided the following documentation:
https://drive.google.com/drive/folders/1vVAnJ01cI92SK6UzdUwaNNUex-4Z6yMw
During the manual phase of the audit, Vidma team manually looks through the code in order to find any security issues, typos, or discrepancies with the logic of the contract.
Within the testing part, Vidma auditors run integration tests using the Truffle testing framework. The test coverage and the tests themselves are inserted into this audit report.
Vidma team uses the most sophisticated and contemporary methods and techniques to ensure the contract does not have any vulnerabilities or security risks:
For the convenience of reviewing the findings in this report, Vidma auditors classified them in accordance with the severity of the issues. (from most critical to least critical). The acceptance criteria are described below.
All issues are marked as "Resolved" or "Unresolved", depending on whether they have been fixed by POP Network or not. The latest commit, indicated in this audit report should include all the fixes made.
To ease the explanation, the Vidma team has provided a detailed description of the issues and recommendations on how to fix them.
Hence, according to the statements above, we classified all the findings in the following way:
Critical | Invalid
Only devaddr can call updatePendingInfo() function where reward multiplier is changed. When in some cases this function won’t call or will call with some delays it will lead to outdated info that triggers incorrect reward distribution so the user will be able to lose his accumulated reward.
Consider fixing the updating reward multiplier in a more trusted and decentralized way. Or add some validation to prevent user deposit or withdrawal before the pending reward info won’t be updated.
Explanation from the POP Network team: “We are logging masternode running time on server and update staking contract on the server-side. We are updating these infos every some period and we let users know when we update infos. We know it's too centralized but it's a good choice for now.”
Critical | Resolved
In the emergencyWithdraw() function user should be able to withdraw the available deposited amount. In the current logic before transferring the user’s funds user.amount value is set to zero in line 119 and only after that appears transfer where the passed amount is variable user.amount which was set to zero before. In this case, the user can’t be able to withdraw his funds and after a call of emergencyWithdraw() function user’s funds will be locked in the contract balance without any chance to withdraw it.
Consider fix logic of the emergencyWithdraw() function.
Critical | Resolved
The reward is transferred to the user when the user deposits and withdraws. To transfer rewards used safePopTransfer() function. When the staking contract won’t have enough pop tokens to cover the reward distribution all available tokens will be transferred to the user which will be less than the actually accumulated reward. There is no tracking of the reward transferring so if the user withdraws staked tokens as it is (with fewer rewards amount) he won’t be able to withdraw the missing amount.
Consider managing case when there are not enough tokens to withdraw for reward in that case so the user will not loss.
Low | Resolved
Ignored return value of transferFrom and transfer in the functions deposit, withdraw, emergencyWithdraw, safePopTransfer in lines 94, 112, 122, 131, 133.
Consider validating return value by wrapping transfer/transferFrom in require or using SafeERC20 library.
In line 13 there is defined library usage using SafeERC20Upgradeable for IERC20; but functionality from SafeERC20Upgradeable library is not used in the codebase. For transfer tokens used simple transfer/transferFrom but not safeTransfer/safeTransferFrom.
Fixed.
Low | Resolved
There is no check if the given param _amount is available for the deposit as the available amount for staking starts from 50K POP tokens.
Consider adding a check for the local variable “amount” to check if the depositing amount isn’t zero.
Comment from POP Network team: “We use deposit function for claim rewards. So if we input amount as zero, then it only claims rewards.”
We may suggest you add separate function for claiming rewards, so user can spend less gas for calling claiming transaction.
Fixed.
Low | Resolved
In line 94 of function deposit() and in line 109 of function withdraw() there is no check if claimable user rewards are greater than 0.
Consider adding a check for claimable amounts to not perform token transfer if the amount of rewards is equal to 0.
Low | Resolved
The current version of solc is ^0.6.12 and it is better to lock the pragma to a specific version.
Contracts should be deployed with the same compiler version and flags that they have been tested with thoroughly. Locking the pragma helps to ensure that contracts do not accidentally get deployed using, for example, an outdated compiler version that might introduce bugs that affect the contract system negatively.
Lock pragma to a specific version.
Low | Resolved
It is best practice to set the visibility of state variables explicitly. The default visibility for cycleLen in line 28 is internal.
Explicitly specify the visibility of state variables.
Low | Resolved
In functions initialize() and dev() there is no check if the _devaddr address isn't a zero address.
Consider adding a check for zero address for functions initialize() and dev().
Low | Resolved
Functions getMultiplier(), deposit(), withdraw(), emergencyWithdraw(), updatePendingInfo() and dev() can be marked as external as they are not used in the contract.
Consider changing visibility from public to external to safe gas usage on calling these functions.
Low | Resolved
Functions getMultiplier() state visibility can be restricted to pure.
Consider changing state visibility in getMultiplier() from view to pure.
Low | Resolved
There is no check if the given param _amount isn’t zero.
Consider adding a check for zero value.
Low | Resolved
There is no check if the user has any funds to withdraw.
Consider adding a check for zero value.
Low | Resolved
There is no check if the input param _popPerBlock isn’t zero.
Consider adding a check for zero value.
Low | Resolved
In line 141 getPopPerBlock() function can return 0.
Consider managing case when function getPopPerBlock() return zero while calculating value of divider.
Informational | Resolved
Smart contract Stakel is not covered by NatSpec annotations.
Consider covering by NatSpec all contract methods.
Defined only @notice section but @param and @return sections are not disclosed.
Fixed.
Informational | Resolved
In line 5 in the codebase there commented import statement for SafeERC20.sol, but in line 6 there used SafeERC20Upgradeable.sol.
Remove redundant import statement.
Informational | Resolved
Constant stakeUnit is not in UPPER_CASE_WITH_UNDERSCORES .
Consider fixing the naming style according to the solidity style guide.
Informational | Resolved
The POP Network team didn’t share any type of documentation with the Vidma team.
Consider providing some documentation.
To verify the contract security and performance a bunch of integration tests were made using the Truffle testing framework.
Tests were based on the functionality of the code, business logic, and requirements and for the purpose of finding the vulnerabilities in the contacts.
In this section, we provide both tests written by POP Network and Vidma auditors.
POP Network Coverage – 78.13%
Vidma Coverage – 100%
Industry Standard – 95%
It’s important to note that Vidma auditors do not modify, edit or add tests to the existing tests provided in the POP Network repo. We write totally separate tests with code coverage of a minimum of 95%, to meet the industry standards.
We are delighted to have a chance to work together with POP Network team and contribute to their success by reviewing and certifying the security of the smart contracts.
The statements made in this document should not be interpreted as investment or legal advice, nor should its authors be held accountable for decisions made based on them.
A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!
Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere.
The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.
A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!
Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.
The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.
A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!
Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.
Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.
The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.
A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!
Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.