Introduction
We express our gratitude to the DeXe Network team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.
DeXe Network is a platform for Defi asset management.
title | content |
---|---|
Platform | EVM |
Language | Solidity |
Tags | DEX, Lending Platform, Voting, DAO |
Timeline | 01/03/2023 - 22/06/2023 |
Methodology | https://hackenio.cc/sc_methodology→ |
Review Scope | |
---|---|
Repository | https://github.com/dexe-network/investment-contracts→ |
Commit | bd1044eba1007aa2aceed28b4e9e6a070aa7ef5a |
Review Scope
- Commit
- bd1044eba1007aa2aceed28b4e9e6a070aa7ef5a
Audit Summary
10/10
100%
10/10
10/10
The system users should acknowledge all the risks summed up in the risks section of the report
Document Information
This report may contain confidential information about IT systems and the intellectual property of the Customer, as well as information about potential vulnerabilities and methods of their exploitation.
The report can be disclosed publicly after prior consent by another Party. Any subsequent publication of this report shall be without mandatory consent.
Document | |
---|---|
Name | Smart Contract Code Review and Security Analysis Report for DeXe Network |
Audited By | Hacken |
Website | https://www.dexe.network→ |
Changelog | 08/03/2023 - Initial Review |
12/04/2023 - Second Review | |
22/05/2023 - Third Review | |
22/06/2023 - Fourth Review |
Document
- Name
- Smart Contract Code Review and Security Analysis Report for DeXe Network
- Audited By
- Hacken
- Website
- https://www.dexe.network→
- Changelog
- 08/03/2023 - Initial Review
- 12/04/2023 - Second Review
- 22/05/2023 - Third Review
- 22/06/2023 - Fourth Review
System Overview
DeXe Network is a platform for Defi asset management.
It supports the following features for users:
create a personalized trading token,
copy other wallets,
save and multiply assets by investing in existing traders on the platform.
The system consists of the following contracts:
ContractRegistry - a contract that stores addresses of all other DeXe contracts.
PoolFactory - a contract that allows deploying trading and government pools.
CoreProperties - a storage contract for shared properties between DeXe contracts.
PriceFeed - Uniswap wrapper to exchange tokens and receive their price.
Insurance - a contract that allows buying insurance and that manages insurance claims (off-chain).
UserRegistry - a storage contract for users' info.
TraderPool - an abstract pool that implements basic trading pools logic, like investment, divestment, and trading. After investment mints LP tokens.
BasicTraderPool - implementation of TraderPool that allows the creation of RiskyProposal. RiskyProposal - a sub-pool of parent pool that has its own LP tokens. To create a RiskyProposal - the trader should specify a token for the proposal pool.
InvestTraderPool - implementation of TraderPool that allows the creation of proposals for different types of investments that are out of contract’s control (like off-chain investments).
TraderPoolInvestProposal - a contract that handles the logic of proposals created by InvestTraderPool.
TraderPoolRiskyProposal - a contract that handles the logic of proposals created by BasicTraderPool.
GovUserKeeper - a vault storing information about users, their ERC20 tokens and NFTs.
GovPool - voting contract which stores proposals, votes for them and access rights.
ContractsRegistry - holds string constants.
TokenSaleProposal - implementation of ITokenSaleProposal that acts as a class for proposals of token sales in the system.
GovUserKeeperLocal - a library containing two validation methods.
GovUserKeeperView - a contract which acts as a proxy to view the state on GovUserKeeper.
GovPoolCommission - a contract to pay commission to commission receivers.
GovPoolExecute - a contract to execute proposals.
GovPoolRewards - a contract to provide rewards payments.
ShrinkableArray - a custom data structure, an array which can shrink in size.
GovPoolStaking - a contract to act as a Front-end for staking and updating rewards in the Micropools.
GovPoolUnlock - a contract with a single function unlockInProposals() which unlocks proposals if conditions are met.
GovPoolView - a contract which provides several view functions to view withdrawable assets and get users’ proposals.
GovPoolVote - a contract which acts as an external Front-end to make votes in GovPool.
GovPoolOffchain - a contract to trigger saving results off-chain.
DataHelper - a helper contract with two functions returning blockchain-related programmatic values.
AddressSetHelper - a helper contract which adds addresses to an address array.
MathHelper - a helper contract with two Math helper methods.
GovSettings - a contract to keep arrays of settings for various executors.
ERC20Sale - a governance ERC20 token.
GovValidators - a pool of validators and proposals.
GovValidatorsToken - an ERC20 governance token.
ERC721Multiplier - an ERC721 token with multiplying and rewards functionalities.
ERC721Power - an extended version of an ERC721 token.
DistributionProposal - a type of proposal representing token distribution.
PoolRegistry - a contract which acts as a registry of pools.
GovTokenSaleDeployer - a library to deploy a token sale via proxy.
Privileged roles
The CoreProperties contract has the following privileged roles:
Owners can:
Add/remove whitelist tokens.
Add/remove blacklist tokens.
Set the maximum pool investors number.
Set the maximum open positions number.
Set trader leverage params.
Set commission init and duration times.
Set DeXe commissions percentages.
Set the trader commission percentage.
Set delay for risky pool.
Set insurance parameters.
Set gov vote limit.
The PoolRegistry contract has the following privileged roles:
Pool Factory can:
Associate users with a pool.
Add a proxy pool.
The Insurance contract has the following privileged roles:
Owners can:
Accept claims.
The TraderPool contract has the following privileged roles:
Trader admins can:
Modify admins.
Modify private investors.
Change pool parameters.
Reinvest commissions.
Exchange.
BABT holders can:
Invest.
Divest.
Trader pool contract can:
Mint and burn LP tokens.
Update users’ balances.
The BasicTraderPool contract has the following privileged roles:
Traders can:
Create proposals.
Exchange.
BABT holders can:
Invest in proposals.
Reinvest from proposals.
Proposal pool can:
Add/remove users from investors.
The InvestTraderPool contract has the following privileged roles:
Traders can:
Create proposals.
Exchange.
Invest after investment delay.
BABT holders can:
Invest in proposals.
Reinvest from proposals.
Proposal pool can:
Add/remove users from investors.
The TraderPoolInvestProposal contract has the following privileged roles:
Trader admins can:
Change proposal restrictions.
Withdraw funds from proposals to traders’ wallet.
Supply proposals with traders’ own funds.
Convert investment base to dividents.
Parent trader pool can:
Create proposals.
Invest into proposals.
Divest from proposals.
The GovValidators contract has no directly-specified privileged roles, but only addresses holding govValidatorsToken tokens can vote for proposals in it.
The ContractsRegistry contract is inherited from OwnableContractsRegistry, but has no mutating functionality or any role-based privileges.
The GovSettings contract has the following privileged role:
Owners can:
Edit settings.
Change executors.
Add settings.
The ERC20Sale contract has the following privileged role:
Governance can:
Mint.
Burn.
Pause.
Unpause.
The GovPool contract has the following privileged role:
BABTHolders can:
Vote for proposals.
Deposit NFTs.
Withdraw NFTs.
Delegate NFTs to someone.
Undelegate.
Unlock user’s proposals.
Execute proposals.
Claim rewards.
Save off-chain results.
The GovUserKeeper contract has the following privileged role:
Owner can:
Deposit tokens.
Withdraw tokens.
Delegate tokens.
Undelegate tokens.
Deposit NFTs.
Withdraw NFTs.
Delegate NFTs.
Undelegate NFTs.
Create NFT Power Snapshots.
Update max amount of locked tokens.
Lock tokens.
Unlock tokens.
Lock NFTs.
Unlock NFTs.
Update NFT powers.
Set ERC20 address.
Set ERC721 address.
The GovValidators contract has the following privileged roles:
Owners can:
Create an external proposal.
Holders of Governance tokens can:
Create an internal proposal.
Vote.
The ERC721Multiplier contract has the following privileged role:
Owners can:
Mint NFTs.
Set base URI.
The ERC721Power contract has the following privileged role:
Owners can:
Set NFT max power.
Set required collateral for an NFT.
Mint NFT.
Set base URI.
The DistributionProposal contract has the following privileged role:
Governors contract can:
Execute proposals.
The TokenSaleProposal contract has the following privileged role:
Governors can:
Add to whitelist.
Create a tier.
Turn off a specific tier info view.
The PoolRegistry contract has the following privileged role:
Pool factory can:
Add a proxy pool.
Associate user with a pool.
The Insurance contract has the following privileged role:
Owners can:
Accept insurance claim.
Recommendations
With BasicTraderPool.investProposal, the access control is onlyBABTHolder, with GovPool, the createProposal
function access control is onlyBABTHolder. The onlyBABTHolder access control might not be sufficient for security. Following the Check Effects Interaction Pattern or using ReentrancyGuard → is recommended in these cases.
Executive Summary
Documentation quality
The total Documentation quality score is 10 out of 10.
Provided documentation well describes the project.
Code quality
The total Code quality score is 10 out of 10.
Code is well written, with scalable architecture and divided with components that follow the single responsibility principle.
Missing events for some critical state changes are found.
Test coverage
Code coverage of the project is 100%.
Security score
Upon auditing, the code was found to contain 2 critical, 14 high, 7 medium, and 10 low severity issues. Out of these, 15 issues have been addressed and resolved, leading to a Security score of 10 out of 10.
All identified issues are detailed in the “Findings” section of this report.
Summary
The comprehensive audit of the customer's smart contract yields an overall score of 10. This score reflects the combined evaluation of documentation, code quality, test coverage, and security aspects of the project.
Risks
The system is composed of multiple upgradable contracts. In case of owner keys leak, unauthorized users may receive access to user funds.
TraderPoolInvestProposal allows traders to withdraw invested funds to traders’ wallets. There are no guarantees that investors would take their funds back.
TraderPoolRiskyProposal enables trading of custom tokens. Potential fraud may happen through the creation and manipulation of malware coins. This may result in user investment loss during trading in risky pools.
Users may receive no insurance claims. Decisions on paying insurance are done off-chain or on with out-of-scope contracts.
Findings
Code ― | Title | Status | Severity | |
---|---|---|---|---|
F-2023-0437 | Flashloan Attack; Front-Running Attack | mitigated | Critical | |
F-2023-0436 | Unverified Interaction | mitigated | Critical | |
F-2023-0451 | Requirements Violation; Misleading Naming | mitigated | High | |
F-2023-0450 | Upgradeability Issues | fixed | High | |
F-2023-0449 | Access Control Violation; Race Conditions | mitigated | High | |
F-2023-0448 | Denial of Service Vulnerability | fixed | High | |
F-2023-0447 | Highly Permissive Role Access | fixed | High | |
F-2023-0446 | Denial of Service Vulnerability | mitigated | High | |
F-2023-0445 | Integer Overflow | fixed | High | |
F-2023-0444 | Highly Permissive Role Access | fixed | High |
Identify vulnerabilities in your smart contracts.
Appendix 1. Severity Definitions
When auditing smart contracts, Hacken is using a risk-based approach that considers Likelihood, Impact, Exploitability and Complexity metrics to evaluate findings and score severities.
Reference on how risk scoring is done is available through the repository in our Github organization:
Severity | Description |
---|---|
Critical | Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation. |
High | High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation. |
Medium | Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category. |
Low | Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution, do not affect security score but can affect code quality score. |
Severity
- Critical
Description
- Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation.
Severity
- High
Description
- High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation.
Severity
- Medium
Description
- Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category.
Severity
- Low
Description
- Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution, do not affect security score but can affect code quality score.
Appendix 2. Scope
The scope of the project includes the following smart contracts from the provided repository:
Scope Details | |
---|---|
Repository | https://github.com/dexe-network/investment-contracts→ |
Commit | bd1044eba1007aa2aceed28b4e9e6a070aa7ef5a |
Whitepaper | Provided→ |
Requirements | Not provided |
Technical Requirements | Not provided |
Scope Details
- Commit
- bd1044eba1007aa2aceed28b4e9e6a070aa7ef5a
- Whitepaper
- Provided→
- Requirements
- Not provided
- Technical Requirements
- Not provided
Custom dependencies |
---|
https://www.npmjs.com/package/@dlsl/dev-modules/v/1.9.0→ |
libs/arrays/Paginator.sol |
libs/arrays/ArrayHelper.sol |
pool-contracts-registry/pool-factory/AbstractPoolFactory.sol |
libs/data-structures/StringSet.sol |
libs/decimals/DecimalsConverter.sol |
pool-contracts-registry/presets/OwnablePoolContractsRegistry.sol; contracts-registry/AbstractDependant.sol |
Custom dependencies
- https://www.npmjs.com/package/@dlsl/dev-modules/v/1.9.0→
Custom dependencies
- libs/arrays/Paginator.sol
Custom dependencies
- libs/arrays/ArrayHelper.sol
Custom dependencies
- pool-contracts-registry/pool-factory/AbstractPoolFactory.sol
Custom dependencies
- libs/data-structures/StringSet.sol
Custom dependencies
- libs/decimals/DecimalsConverter.sol
Custom dependencies
- pool-contracts-registry/presets/OwnablePoolContractsRegistry.sol; contracts-registry/AbstractDependant.sol
Contracts in Scope
contracts/gov/user-keeper/GovUserKeeper.sol
contracts/gov/GovPool.sol
contracts/gov/proposals/TokenSaleProposal.sol
contracts/gov/proposals/DistributionProposal.sol
contracts/gov/validators/GovValidators.sol
contracts/gov/validators/GovValidatorsToken.sol
contracts/gov/ERC721/ERC721Power.sol
contracts/gov/ERC721/ERC721Multiplier.sol
contracts/gov/settings/GovSettings.sol
contracts/gov/ERC20/ERC20Sale.sol
contracts/trader/TraderPoolRiskyProposal.sol
contracts/trader/TraderPool.sol
contracts/trader/TraderPoolInvestProposal.sol