CertiK reviewed Hyperchain X (HyperChainX-Audit) on 9 Mar 2023: 12 findings, 0 critical; 1 marked fixed, 11 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 | 0 |
| Low | 9 | 0 | 1 |
In the contract `HYPERCHAIN` the role `_owner` has authority over the functions shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority.  In the contract `HYPERCHAIN` the role `operator` has authority over the functions shown in the diagram below. Any compromise to the `operator` account may allow the hacker to take advantage of this authority.  In the contract `Ownable` the role `_owner` has authority over the functions shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority. 
All of the `HYPER` tokens are sent to the `operator` when deploying the contract. This could be a centralization risk as the `operator` can distribute tokens without obtaining the consensus of the community. Since the privilege of the `operator`, it is possible of being maliciously manipulated by hackers if the account of the owner was compromised.
The `isContract` check cannot cover all scenarios. The check can be bypassed if the call is from the constructor of a contract or when the contract is destroyed. In that case, `isContract` will return `false` because its `codesize` will be zero. The comment in the `isContract` implementation from the OpenZeppelin library also says that "it is unsafe to assume that an address for which this function returns false is an externally-owned account (EOA) and not a contract." - Reference: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/3dac7bbed7b4c0dbf504180c33e8ed8e350b93eb/contracts/utils/Address.sol ```solidity=935 require(!isContract(newProjectWallet), "Cannot be contract address"); ```
There should always be events emitted in the sensitive functions that are controlled by centralization roles.
Addresses should be checked before assignment or external call to make sure they are not zero addresses. ```solidity=394 operator = _operator; ``` - `_operator` is not zero-checked before being used.
A sandwich attack might happen when an attacker observes a transaction swapping tokens or adding liquidity without setting restrictions on slippage or minimum output amount. The attacker can manipulate the exchange rate by frontrunning (before the transaction is attacked) a transaction to purchase one of the assets and make profits by back running (after the transaction is attacked) a transaction to sell the asset. The following functions are called without setting restrictions on slippage or minimum output amount, so transactions triggering these functions are vulnerable to sandwich attacks, especially when the input amount is large: - `uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens()` - `uniswapV2Router.swapExactETHForTokensSupportingFeeOnTransferTokens()`
The condition `!_isExcluded[sender] && !_isExcluded[recipient]` can be included in `else` .
State variables that never change should be declared as `constant` to save gas. ```solidity=275 string private _name = "HYPERCHAIN"; ``` - `_name` should be declared `constant`. --- ```solidity=276 string private _symbol = "HYPER"; ``` - `_symbol` should be declared `constant`. --- ```solidity=277 uint8 private _decimals = 7; ``` - `_decimals` should be declared `constant`.
The return value of the transfer()/transferFrom() call is not checked. ```solidity=514 ERC20token.transfer(msg.sender, balance); ```
Variable `_rOwned[account]` is not updated in the function `includeInReward()`, which will make the accounts included siphon off the tokens out of the balances of all token holders. The Rate was higher at the moment of the `excludeFromReward(account)` call, so the `_rOwned[account] / _tOwned[account]` ratio is bigger than expected for accounts included in the reward. ```solidity=491 function includeInReward(address account) external onlyOwner() { require(_isExcluded[account], "Account is already included"); for (uint256 i = 0; i < _excluded.length; i++) { if (_excluded[i] == account) { _excluded[i] = _excluded[_excluded.length - 1]; _tOwned[account] = 0; _isExcluded[account] = false; _excluded.pop(); break; } } } ```
The linked variables assigned in the constructor can be declared as `immutable`. Immutable state variables can be assigned during contract creation but will remain constant throughout the lifetime of a deployed contract. A big advantage of immutable variables is that reading them is significantly cheaper than reading from regular state variables since they will not be stored in storage.
| Address | Chain | Source code |
|---|---|---|
| 0xee5b…fc280xee5b03b769ca6c690d140cafb52fc8de3f38fc28 | Chain: BNB Chain | Source code: Verified source |
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