CertiK reviewed Empire (Empire v3) on 1 Mar 2023: 20 findings, 0 critical; 6 marked fixed, 7 acknowledged, 7 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 | 0 | 4 | 0 |
| Medium | 0 | 3 | 1 |
| Low | 7 | 0 | 5 |
In the contract `Bridge` the role `validator` has authority over the functions below: - function `redeem()`: to transfer tokens to another chain. Any compromise to the `validator` account may allow the hacker to take advantage of this authority. In the contract `Bridge` 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 `EmpireToken` the role `_owner` has authority over the functions shown in the diagram below.  Besides, the role `_owner` also has authority over the function `setBridgeVault()`, which is used to set the `bridgeVault` by the owner. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority. In the contract `EmpireToken` the role `bridge` has authority over the functions shown in the diagram below.  Any compromise to the `bridge` account may allow the hacker to take advantage of this authority.
The `addLiquidity` function calls the `uniswapV2Router.addLiquidityETH` function with the `to` address specified as `liquidityWallet` for acquiring the generated LP tokens from the `EmpireToken-BNB` pool. As a result, over time the `liquidityWallet` address will accumulate a significant portion of LP tokens. If the `liquidityWallet` is an EOA (Externally Owned Account), mishandling its private key can have devastating consequences for the project. ```solidity= function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private { _approve(address(this), address(uniswapV2Router), tokenAmount); uniswapV2Router.addLiquidityETH{value: ethAmount}( address(this), tokenAmount, 0, 0, liquidityWallet, block.timestamp ); } ```
The logic ensures the cross-chain transaction atomicity is not implemented in the contract. The `validator` could be a message server host by the owner or an intermediate 3rd party application, hence the parameters in the `redeem()` function could not be guaranteed to correspond to the `swap()`. The scope of the audit treats the above-mentioned application entities as black boxes and assumes their functional correctness. However, in the real world, 3rd parties can be compromised, which may lead to lost or stolen assets. Suppose the cross-chain transaction atomicity is not guaranteed properly. In that case, the user deposits tokens into the source chain, but not be able to redeem the correct token amount from the target chain.
The implementation of the `isContract` check can not cover all scenarios. The check can be bypassed if the call is from the constructor of a smart contract or when the contract is destroyed. Because, in that case, the code size will also be zero.
Generally, deflationary tokens are incompatible with DEX and special rules need to be coded for DEX addresses eg. excluding them from reward. Otherwise, a hacker can exploit the protocol using the reflection mechanism. The balance of accounts that include rewards is calculated by `rAmount/rate`, where the rate is determined base on the total supply. If the `deliver()` function is executed with significant input, it can significantly decrease `rTotal`, thereby allowing for manipulation of the rate.
```solidity function includeInReward(address account) external onlyOwner() { require(account != bridgeVault, "Bridge Vault can't receive reward"); 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; } } } ``` 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.
| Address | Chain | Source code |
|---|---|---|
| 0x51a1…15d40x51a183d8d79df6892ab7b8f57b33ba70599515d4 | Chain: BNB Chain | |
| 0x62ab…8bf40x62ab5437563fc655226239ca8146f727e1d28bf4 | Chain: BNB Chain | Source code: Verified source |
| 0x0ba7…b4f30x0ba7529fd0ea0ca208313f3fb280a91dfae1b4f3 | 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