CertiK reviewed Decubate on 30 May 2023: 26 findings, 0 critical; 16 marked fixed, 10 open.
Report hosted on skynet.certik.com.
Trustblock does not review code.
Statuses are the security firm’s own, from its report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 2 | 0 | 0 |
| Medium | 0 | 0 | 4 |
| Low | 8 | 0 | 12 |
### Factory.sol #### DEFAULT_ADMIN_ROLE In the contract `Factory` the role `_owner` has authority over the functions shown in the list below. * addOption() - Add new price option * setOption() - Sets name, length, and price of price option * setBuyBackSettings() - Sets buyback settings * setNewInmplementation() - Sets new farm implementation contract Any compromise to the `_owner` account may allow the hacker to take advantage of this authority to set important settings. #### deployers In the contract `Factory` the role `deployers` has authority over the functions shown in the list below. * transferToken() - Transfers token from `Farm` address to deployer address Any compromise to the `_owner` account may allow the hacker to take advantage of this authority to transfer tokens out of the `Farm` address. ### Farm.sol #### _owner In the contract `DecubateFarm` the role `_owner` has authority over the functions shown in the list below. * transferToken() - Transfers token to a specified address * set() - Sets current option and pool end date Any compromise to the `_owner` account may allow the hacker to take advantage of this authority to transfer tokens and control pool settings. ### DCBFactory.sol #### DEFAULT_ADMIN_ROLE In the contract `DCBFactory` the role `DEFAULT_ADMIN_ROLE` has authority over the functions shown in the list below. * changeImplementations() - Change registered addresses for the vesting, crowdfunding, and token claim implementations * setManagerRole() - Grant and revoke manager role to set address Any compromise to the `DEFAULT_ADMIN_ROLE` account may allow the hacker to take advantage of this authority to set contract implementation addresses and appoint managers. #### _event In the contract `DCBFactory` the role `_event` has authority over the functions shown in the list below. * setUserInvestment() - Sets user investments within crowdfunding and token claim contracts Any compromise to the `_event` account may allow the hacker to take advantage of this authority to set user investments within crowdfunding and token claim contracts. #### MANAGER_ROLE In the contract `DCBFactory` the role `MANAGER_ROLE` has authority over the functions shown in the list below. * deployCrowdfunding() - Deploy crowdfunding contract as a clone of crowdfunding implementation contract * deployTokenClaim() - Deploy token claim contract as a clone of token claim implementation contract Any compromise to the `_event` account may allow the hacker to take advantage of this authority to deploy crowdfunding and token claim contracts. ### DCBPlatformVesting.sol #### _owner In the contract `DCBPlatformVesting` the role `_owner` has authority over the functions shown in the list below. * setTokenClaimWhitelist() - Sets whitelist for token claim contract * setCrowdfundingWhitelist() - Sets whitelist for crowdfunding contract Any compromise to the `_owner` account may allow the hacker to take advantage of this authority to set whitelists. #### innovator In the contract `DCBPlatformVesting` the role `innovator` has authority over the functions shown in the list below. * claimRaisedFunds() - Allow project owner to claim funds raised from fundraising Any compromise to the `innovator` account may allow the hacker to take advantage of this authority to claim funds. ### DCBTokenClaim.sol #### MANAGER_ROLE In the contract `DCBTokenClaim` the role `MANAGER_ROLE` has authority over the functions shown in the list below. * registerByManager() - Register multiple users for allocation. * setMinTierForClaim() - Set the minimal tier. Any compromise to the `MANAGER_ROLE` account may allow the hacker to take advantage of this authority to add any number of users.
DCBFactory.sol is an upgradeable contract, the owner can upgrade the contract without the community's commitment. If an attacker compromises the account, he can change the implementation of the contract and drain tokens from the contract.
Any user can deploy a farm and later any other user can extend the farm since both functions are accessible to any and all external users. The `deploy()` function is a public function as shown below. ```solidity=115 function deploy(DeployParams memory params) public optionExists(params._option) returns (address) { ``` The `extendFarm()` function is an external function as shown below. ```solidity=167 function extendFarm(uint256 _farm, uint256 _option) external optionExists(_option) farmExists(_farm) { ``` The audit team would like to check to see if this is intended and whether there will be controls in place to prevent malicious users from creating pools that are not intended to be used for the public good or to run scams.
It was noted that the allocation used for comparison in function `fundAgreement()` is multiplied by the `multi` factor twice, especially in the case when there is no guaranteed allocation, as in the code below. The allocation calculation executes a call to function `getAllocationForTier()`. ``` solidity=273 } else { (bool _flag, uint256 _tier, uint256 _multi) = tiers.getTierOfUser(msg.sender); if (_flag) { alloc = getAllocationForTier(uint8(_tier), uint8(_multi)); } } ``` The comparison is located in the require statement as shown below. ``` solidity=281 require( dcbAgreement.investorList[msg.sender].investAmount.add(_investFund) <= alloc.mul(multi), "Amount greater than allocation" ); ``` The calculation in function `getAllocationForTier()` is as follows: ```solidity=357 function getAllocationForTier(uint8 _tier, uint8 _multi) public view returns (uint256) { return ((((2 ** _tier) * _multi).mul(dcbAgreement.hardcap)).div(totalShares)); } ``` The factor `_multi` is already used in the calculation of the `alloc` amount, which is the return value from the calculation above. The audit team would like to understand the logic of the require statement to ensure that it matches the intended design.
It was noted that there are two different ways to call the `claimDistribution()` function - one from the `DCBFactory` contract and the other in the `DCBPlatformVesting` contract. The claim distribution function in the `DCBPlatformVesting` contract is as follows: ```solidity=239 function claimDistribution(address _wallet) public returns (bool) { uint256 idx = vestingPool.hasWhitelist[_wallet].arrIdx; WhitelistInfo storage whitelist = vestingPool.whitelistPool[idx]; require(!whitelist.refunded, "user has already been refunded"); uint256 releaseAmount = calculateReleasableAmount(_wallet); require(releaseAmount > 0, "Zero amount to claim"); whitelist.distributedAmount = whitelist.distributedAmount.add(releaseAmount); vestedToken.transfer(_wallet, releaseAmount); emit Claim(_wallet, releaseAmount, block.timestamp); return true; } ``` ```solidity=185 function claimDistribution(address _event) external returns (bool) { require(events[_event].vestingAddress != address(0), "Vesting is not active"); IDCBPlatformVesting vesting = IDCBPlatformVesting(events[_event].vestingAddress); return vesting.claimDistribution(msg.sender); } ``` Although there are no vulnerabilities associated with this type of implementation, the audit team would like to better understand what are the two cases for which this function will be called, since it was noted that both function implementations are public and can be called by anyone.
It was noted that the base for the variable `refundFee` is 10_000 whereas for most other percentage values, the base is 1_000. The base used in the `refund()` function for `refundFee` is as follows. The base used is 10_000. ```solidity=166 uint256 fee = whitelist.value * refundFee / 10_000; ``` An example of other percentages is as follows. The base used is 1_000. ```solidity=398 uint256 initial = whitelist.amount.mul(vest.initialUnlockPercent).div(1000); ``` The audit team would like to confirm with the team to see whether this is the intended design since the implementation of the `tiers` contract (which the `refundFee`) was extracted from was not provided and not in the scope of this audit.
In the `DCBCrowdfunding` contract, the function `fundAgreement()` has a section of code that is as follows. ```solidity=257 if (block.timestamp < dcbAgreement.startDate.add(8 hours)) { isGa = true; // second 8 hours is FCFS - 2x allocation } else if (block.timestamp < dcbAgreement.startDate.add(16 hours)) { multi = 2; // final 8 hours is Free for all - 10x allocation } else { multi = 10; // @audit discussion - Why increasing allocation } ``` In the above code it seems like participants that join later on get the opportunity to stake higher allocations. There are also no requirements to have completed any of the prior levels like in tests to get get access to these higher allocations. The audit team would like to confirm whether this is the intended design since it seems unfair to users who have made earlier allocations.
The `Farm` contract does not currently have any restrictions on the amount of time that a user must stake before they can unstake their tokens. This could have potential impacts on the ecosystem if staking is used for any other functions outside of earning rewards, such as voting. The audit team would like to confirm that this implementation is according to the intended design.
When creating a new instance of a contract from upgradeable contract’s code, these creations are handled directly by Solidity and not by OpenZeppelin Upgrades, which means that these contracts will not be upgradeable.
The use of uint8 or any variables less than uint256 is usually not efficient since the Ethereum Virtual Machine(EVM) will, in the case of uint8, store the 8 bits of the uint8 variable and then fill the extra 248 bits (for a total of 256 bits) with zeros.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (6)
1,044 projects reviewed · 1,375 reports · latest May 2025
See CertiK’s auditsSomething wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.
Tell us