BlockApex (Auditor) was contracted by Dafi Protocol (Client) for the purpose of conducting a Smart Contract Audit/Code Review. This document presents the findings of our analysis which took place from 16th Dec 2021 to 14th Jan 2022.
Document log: Initial Audit: 31st December 2021 (complete)
Formal verification using property-based testing: 15th January 2022
Final Audit: 17th January 2022.
Scope
The git-repository shared was checked for common code violations along with vulnerability-specific probing to detectmajor issues/ vulnerabilities. Some specific checks are as follows:
Dafi Protocol Super Staking V2 is an update to the V1 module released earlier this year (2021) in the month of July. Super Staking V2 claims to offer a more stable APY rate and enhanced distribution of dDAFI rewards by modifying the math behind reward calculation to rather depend only on accumulated amounts of reward every time demand factor changes to calculating the rewards of users as the sum of all rewards in the past adjusted to the latest demand factor.
Aside from the new reward formula, V2 also holds a couple of security improvements where demand factor is now enumerated using the latest price and is fortified by introduction of a delay i.e. a variance tolerance mechanism to ultimately prevent a sudden change in price. This new demand factor is supported by a TWAP calculation to make the price curve less steeper. Although strict monitoring is required, in cases of hackable oracle feeds, the protocol is able to recover from any kind of exploits by updating to an entirely new oracle service.
System Architecture
Codebase:
The system consists of 5 main smart contracts (namely: Staking Manager V2, Staking Database, Rebase Engine, Network Demand, Token Pool) and supplied with external data through 2 more contracts of Price Feeds and TVL Feeds.
Note: All of the contracts mentioned above contain onlyOwner modifiers to add, set and/or update configurations.
Manual Review: The audit launched with a recon phase where a manual code review was conducted to clarify the layers of understanding of the complexities and the general flow of the program. We started by reviewing the two main contracts against common solidity flaws. After the reconnaissance phase we wrote unit-test cases to ensure that the functions are performing their intended behavior. Then we began with the line-by-line manual code review.
Property Testing: From the reconnaissance, a handful of properties were also extracted and labeled as Invariants. In the following days of the audit procedure, the invariants were thoroughly tested against a setup flow of Dafi Staking V2 to ensure each of them held its proper definition.
AUDIT REPORT
Executive Summary
The analysis indicates that some of the functionalities in the contracts audited are poorly-secured.
Our team performed a technique called “Filtered Audit”, where the contract was separately audited by two individuals. After their thorough and rigorous process of manual testing, an automated review was carried out using Mythril, MythX, and Slither. All the flags raised were manually reviewed and re-tested.
Our team found:
# of issues
Severity of the risk
0
Critical Risk issue(s)
3
High-Risk issue(s)
0
Medium Risk issue(s)
1
Low-Risk issue(s)
1
Informatory issue(s)
Findings
Below is the summary of our findings from the complete audit. This includes any flags raised from the manual/automated code review, behavioral/scenario testing and the properties tested for formal verification.
In recent events, Oracles and external data sources have been manipulated to the adversary's benefit. We started off with our focus on the integrity of Oracles (Chainlink in this case) in order to make sure that the data imported into the contracts are not compromised.
The Chainlink oracle library method was tested against the following parameters of a standard audit technique.
Third-party (data source) function calls
Data type intact for functions’ return values
Access modifiers and state variables (if any)
function getThePrice() public view override returns (uint) {
(
,
int price,
,
,
) = priceFeed.latestRoundData();
return uint(price);
}
Suggestion: It is advised that a more tested and bonafide data source of TWAPs be considered to make Chainlink’s oracle integrity and reliability as the most optimal.
High-risk
HR-1. MAX_DAFI is always greater than totaldDafiDistributed
Status: Failed
Description
If a program is marked as “ended” before the preset ending duration, that is to say, the elapsed time of the program is less than the program duration, users get revert transactions for staking into the ended program (as seen in the testnet event and confirmed over a fuzzing test scenario with the reason of MAX_DAFI being calculated less than total DAFI distributed till the ending timestamp). This property does not hold at fuzzed inputs;
HR-2. Reward Pool should not have balance if the program has ended and all users have unstaked
Status: Failed
Description
This property claims that the reward pool should be empty after the program has ended and that all the users have unstaked.
HR-2(a). “markProgramEnded()” by owner’s mistake can lock funds of the reward pool
In case of human error if the program is marked ended the reward pool retains an amount of tokens unclaimed against the percentage of tokens staked in first place.
Suggestion: It is advised to have a refund mechanism if program duration is ended. The refund amount of tokens should be equal to MAX_DAFI - (MDI*totalElapsedTime).
HR-3. If a program has ended, users should not be able to stake
Status: Failed
Description
In a simple scenario test, it was confirmed that Staking was allowed even if the program duration is completed and the program is marked as ended which in the understanding of the Auditor team is an (incomprehensible feature) and can be proved to be a loophole of the system in some scenarios.
Suggestion: The modifier stakeCheck should be supplied with some additional check to ensure monitoring of programs marked as ended not to allow staking.
function test_StakeAfterProgramEnded() public {
SetupContracts caller = dapping.users().setup Contract();
hevm.warp(block. timestamp + 500);
// _ms, _md, _pd
uint256 minStakeDays = 1;
uint256 maxDafi = 1000 ether;
uint32 progDuration = 12;
caller.wrapsetStakingParams (minStakeDays, maxDafi, progDuration);
// stakin/ unstaing multiple times for seeding
for (uint256 i = 0; i < 3; i++) {
hevm warp (block. timestamp + 90000);
caller.wrapStake ( 1000000000);
hevm warp(block. timestamp + 90000);
caller.wrapunstake ( 1000000000);
}
caller.wrapMarkProgramEnded();
// stakin/ unstaing multiple times for seeding
for (uint256 i = 0; i < 3; i++)
hevm.warp (block. timestamp + 90000);
caller.wrapStake ( 1000000000);
hevm.warp(block. timestamp + 90000);
caller.wrapUnstake ( 1000000000);
}
assertTrue(false);
}
Low-risk
LR-1. Reward is claimable even after program is ended
Status: Passed
Description
Regardless of the program being ended, users should be able to claim their rewards for their staked dafi tokens. This claim should not be bound by any type of time-related constraints. We checked whether this property would fail in any circumstance but it passed on all fuzzed inputs.
LR-2. Unit tests in the testing and main branch of repo at /test/v2.ts should pass
Status: Failed
Description
Unit tests are critical in proving the developer's expected intention and behavior of the working code hence the set of tests not passing entirely and partially in the testing repository code is slightly questionable.
Informatory issues and Optimizations
IR-1. Memory optimization by using uint8 in place of true/false
Description
Following the best practices and the Solidity design patterns guide and since the client code uses a good number of state variables to manage the switches for staking, unstaking and alike. It is therefore suggested by the auditing team that uint8 type variables can be replaced by the developer in place of true/false on multiple occasions to minimize the memory usage and reduce the code size as an optimization.
DISCLAIMER
The smart contracts provided by the client for audit purposes have been thoroughly analyzed in compliance with the global best practices till date w.r.t cybersecurity vulnerabilities and issues in smart contract code, the details of which are enclosed in this report.
This report is not an endorsement or indictment of the project or team, and they do not in any way guarantee the security of the particular object in context. This report is not considered, and should not be interpreted as an influence, on the potential economics of the token, its sale or any other aspect of the project.
Crypto assets/tokens are results of the emerging blockchain technology in the domain of decentralized finance and they carry with them high levels of technical risk and uncertainty. No report provides any warranty or representation to any third-Party in any respect, including regarding the bug-free nature of code, the business model or proprietors of any such business model, and the legal compliance of any such business. No third-party should rely on the reports in any way, including for the purpose of making any decisions to buy or sell any token, product, service or other asset. Specifically, for the avoidance of doubt, this report does not constitute investment advice, is not intended to be relied upon as investment advice, is not an endorsement of this project or team, and it is not a guarantee as to the absolute security of the project.
Smart contracts are deployed and executed on a blockchain. The platform, its programming language, and other software related to the smart contract can have its vulnerabilities that can lead to hacks. The scope of our review is limited to a review of the Solidity code and only the Solidity code we note as being within the scope of our review within this report. The Solidity language itself remains under development and is subject to unknown risks and flaws. The review does not extend to the compiler layer, or any other areas beyond Solidity that could present security risks.
This audit cannot be considered as a sufficient assessment regarding the utility and safety of the code, bug-free status or any other statements of the contract. While we have done our best in conducting the analysis and producing this report, it is important to note that you should not rely on this report only - we recommend proceeding with several independent audits and a public bug bounty program to ensure security of smart contracts.
Borderless Money is a decentralized finance protocol redefining how Social Investments are made, using yield-generating strategies and contributing to social causes. An open, borderless digital society, with borderless money, where the goods, services, technology, information, opportunities, and capital can flow through the borders from one hand to many, fairly, transparently.
Unipilot is an automated liquidity manager designed to maximize ”in-range” intervals for capital through an optimized rebalancing mechanism of liquidity pools. Unipilot V2 also detects the volatile behavior of the pools and pulls liquidity until the pool gets stable to save the pool from impairment loss.
omposable smart contracts bring about certain problems in particular during the auditing phase. One of these is the hindering of end-to-end (E2E) testing. Often it is the case that for calling even just one function of a composable smart contract, multiple other contracts are required to be deployed.
Chainpals transaction contract is responsible for handling the multi-phased transactions that take place between a buyer and a seller, each overlooked by escrow managers to make sure everything goes smoothly.
Data breaches and consumer privacy are one of the most alarming security issues in IT space. About 45% of the world’s population uses social media which makes approximately 3.48 billion people to be interacting with any kind of social media network. These tremendous amounts of connections can lead to various kinds of vulnerabilities if the data is gone into the wrong hands creating pretty damaging consequences.
In a world where personal data has become more or less a commodity, the potential advantages provided by zero-knowledge proofs are monumental. By combining them with blockchain technology, a powerful mix of immutability and security can be achieved.
Zunami is a decentralized protocol operating in the Web3 space, specializing in issuing aggregated stablecoins like UZD and zETH. These stablecoins are generated from omnipools that employ various profit-generating strategies. Recently, the protocol was exploited, resulting in a loss of $2.1M.
Dafi’s “dbridge” enables users to bring their ERC-20 $DAFI tokens across from the Ethereum network to Binance Smart Chain, and vice versa, with aims of making $DAFI available on multiple high-speed and low-cost networks.