CertiK reviewed DeFiChain (Quantum bridge) on 10 Mar 2023: 8 findings, 0 critical; 6 marked fixed, 2 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 | 1 |
| Low | 0 | 0 | 5 |
The `bridgeV1` contract does not protect its initialize function. An attacker can call the initializer and assume ownership of the logic contract, whereby he can perform privileged operations that either indirectly break the proxy by destroying the logic contract or trick unsuspecting users into believing that he is the owner of the upgradeable contract. ```solidity=221 function initialize( address _initialAdmin, address _initialOperational, address _relayerAddress, address _communityWallet, uint256 _fee, address _flushReceiveAddress, uint256 _acceptableRemainingDays ) external initializer { __UUPSUpgradeable_init(); __EIP712_init(name, version); _grantRole(DEFAULT_ADMIN_ROLE, _initialAdmin); _grantRole(OPERATIONAL_ROLE, _initialOperational); communityWallet = _communityWallet; relayerAddress = _relayerAddress; transactionFee = _fee; flushReceiveAddress = _flushReceiveAddress; acceptableRemainingDays = _acceptableRemainingDays; }
The current implementation lacks proper sanity checks for the function argument `_newResetTimeStamp`. Setting `_newResetTimeStamp` to an excessively large value would cause the `bridgeToDeFiChain` operation to revert due to the `STILL_IN_CHANGE_ALLOWANCE_PERIOD` error. ```solidity=349 function changeDailyAllowance( address _tokenAddress, uint256 _dailyAllowance, uint256 _newResetTimeStamp ) external { if (!checkRoles()) revert NON_AUTHORIZED_ADDRESS(); if (!supportedTokens.contains(_tokenAddress)) revert ONLY_SUPPORTED_TOKENS(); if (_newResetTimeStamp < block.timestamp + 1 days) revert INVALID_RESET_EPOCH_TIME(); tokenAllowances[_tokenAddress].dailyAllowance = _dailyAllowance; uint256 prevTimeStamp = tokenAllowances[_tokenAddress].latestResetTimestamp; tokenAllowances[_tokenAddress].latestResetTimestamp = _newResetTimeStamp; tokenAllowances[_tokenAddress].currentDailyUsage = 0; emit CHANGE_DAILY_ALLOWANCE(_tokenAddress, _dailyAllowance, prevTimeStamp, _newResetTimeStamp); } ```
There are no upper boundaries for transaction fee in function `changeTxFee()` . It is possible to set the total transaction fee rate up to 100%. ```solidity=435 function changeTxFee(uint256 fee) external onlyRole(DEFAULT_ADMIN_ROLE) { uint256 oldTxFee = transactionFee; transactionFee = fee; emit TRANSACTION_FEE_CHANGED(oldTxFee, transactionFee); } ```
The `BridgeV1` contract serves as the underlying entity to interact with the external dependency `relayer`. The relayer can sign instructions for fund claiming, which users can submit to the blockchain. The scope of the audit treats component that is out of scope as black boxes and assumes their functional correctness.
The computation for each iteration is complex. It could lead to Out-of-gas exception when the number of supported tokens is large. ```solidity=378 function flushFund() external { for (uint256 i = 0; i < supportedTokens.length(); ++i) { address supToken = supportedTokens.at(i); if ( (IERC20(supToken).balanceOf(address(this)) > acceptableRemainingDays * tokenAllowances[supToken].dailyAllowance) && // the same logic as in bridgeToDeFiChain applies here, if we are still // in the period for addingSupport or changingDailyAllowance, we will not flush for that particular token (tokenAllowances[supToken].latestResetTimestamp <= block.timestamp) ) { uint256 amountToFlush = IERC20(supToken).balanceOf(address(this)) - acceptableRemainingDays * tokenAllowances[supToken].dailyAllowance; IERC20(supToken).transfer(flushReceiveAddress, amountToFlush); } } emit FLUSH_FUND(); } ```
The return value of the transfer()/transferFrom() call is not checked in the following lines. ```solidity=265 IERC20(_tokenAddress).transfer(_to, _amount); ``` --- ```solidity=300 IERC20(_tokenAddress).transferFrom(msg.sender, address(this), netAmountInWei); ``` --- ```solidity=301 IERC20(_tokenAddress).transferFrom(msg.sender, communityWallet, netTxFee); ``` --- ```solidity=370 IERC20(_tokenAddress).transfer(msg.sender, amount); ``` --- ```solidity=391 IERC20(supToken).transfer(flushReceiveAddress, amountToFlush); ```
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (2)
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