CertiK reviewed ShibaDoge | ShibDoge (ShibaDoge) on 15 Oct 2024: 26 findings, 0 critical; none marked fixed.
Report hosted on skynet.certik.com.
Statuses are the security firm’s own, from this report. Trustblock does not review code.
Statuses are the security firm’s own, from its report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 5 | 0 | 0 |
| Medium | 1 | 0 | 0 |
| Low | 20 | 0 | 0 |
In the contract `ShibaDoge`, the role `_owner` has authority over the following functions: - `transferOwnership()` will transfer ownership to the new owner. - `renounceOwnership()` will transfer ownership to address(0). - `lock()` will lock for a period of time and the contract will transfer ownership to address(0). - `updateMarketingWallet()` will update marketing wallet. - `updateDevWallet()` will update dev wallet. - `updateExchangeWallet()` will update exchange wallet. - `updatePartnershipsWallet()` will update partnership wallet. - `addBotToBlacklist()` will add an address to blacklist. - `removeBotFromBlacklist()` will remove an address from the blacklist. - `excludeFromReward()` will exclude an address from reward. - `includeInReward()` will include an address with reward. - `excludeFromFee()` will exclude an account from fee. - `includeInFee()` will include an account with fee. - `excludeFromLimit()` will exclude an account from max amount limit. - `includeInLimit()` will include an account with max amount limit. - `setSellFee()` will set `sellFee` which will be used when the recipient is the Uniswap pair. - `setBuyFee()` will set `buyFee` which will be used when the sender is the Uniswap pair. - `setBothFees()` will set both `buyFee` and `sellFee`. - `setNumTokensSellToAddToLiquidity()` will update `numTokensSellToAddToLiquidity` which will be outlier to trigger `swapAndLiquify()`. - `setMaxTxPercent()` will set max transaction amount. - `_setMaxWalletSizePercent()` will set max wallet size. - `setSwapAndLiquifyEnabled()` will set `swapAndLiquify()` function enabled or not. Any compromise to the `_owner` account may allow the hacker to take advantage of this and result in unexpected losses. As of May 11th, 2022, the owner is [0xb2a15506972719d38b5030e6be91c22f9cf99806](https://etherscan.io/address/0xb2a15506972719d38b5030e6be91c22f9cf99806) Furthermore, some collected fees will be transferred to the addresses `_marketingAddress` and `_devwallet`. As a result, over time the addresses will accumulate a significant portion of `ETH`. If the addresses are EOAs (Externally Owned Account), mishandling the private key could lead to attackers stealing the funds from the project.
In transactions, the linked statements may be called and `ETH` owned by the contract is transferred to the centralized addresses `_marketingAddress` and `_devwallet`. As a result, over time the addresses will accumulate a significant portion of `ETH`. If the addresses are EOAs (Externally Owned Account), mishandling of its private key can have devastating consequences to the project as a whole.
The `swapAndLiquify` function converts half of the `contractTokenBalance` ShibaDoge tokens to ETH. The other half of ShibaDoge tokens and part of the converted ETH are deposited into the ShibaDoge-ETH pool on uniswap as liquidity. For every `swapAndLiquify` function call, a small amount of ETH leftover in the contract. This is because the price of ShibaDoge drops after swapping the first half of ShibaDoge tokens into ETHs, and the other half of ShibaDoge tokens require less than the converted ETH to be paired with it when adding liquidity. The contract doesn't appear to provide a way to withdraw those ETH, and they will be locked in the contract forever.
In the constructor, the `_rTotal` minted to the message sender address. This could be a centralization risk as the deployer can distribute `_rTotal` without obtaining the consensus of the community.
Generally, deflationary tokens are incompatible with DEX and special rules need to be coded for DEX addresses e.g. excluding them from reward. Otherwise, a hacker may 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 `burn()` function is executed with significant input, it can significantly decrease `_tTotal`, thereby allowing for manipulation of the rate.
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.
In the ShibaDodge protocol, the "dev address" and "market address" will receive a portion of fees. The conditional statement in L1642~1645 determines the amount of ETH that the dev address can receive. ```solidity=1642 uint256 devAmt = unitBalance * 2 * (buyFee.dev + sellFee.dev) > address(this).balance ? address(this).balance : unitBalance * 2 * (buyFee.dev + sellFee.dev); ``` However, as there could be non-withdrawable ETH accumulated in the contract, the address(this).balance could be a big number, thus leading to `unitBalance * 2 * (buyFee.dev + sellFee.dev)` is always smaller than `address(this).balance`.
The judgment condition does not match the message.
When transfer, if one of the both parties to the transaction are in the fee exclusion list, then the transaction is free of charge. In addition, normal wallet transfer is also free of charge. Otherwise, the transaction fee is set according to the specific circumstances of buy or sell(47% liquidity fee and 48% marketing fee). If the contract account balance exceeds the set value of `numTokensSellToAddToLiquidity`, the `swapAndLiquify` operation will be executed. First, the token of the contract account balance will be divided according to a certain ratio, one part will be converted into ETH (one part will be used to add liquidity, the other part will be transferred to the `_marketingAddress` address and `_devwallet`), and the other part will be used to add liquidity. The lp will be sent to `address(this)`.
The following functions are declared as `public` and are not invoked in any of the contracts contained within the project's scope. The functions that are never called internally within the contract should have external visibility. **contract `Ownable`** - `renounceOwnership()` in L510 - `transferOwnership()` in L519 - `lock()` in L533 - `unlock()` in L541 **contract `ShibaDoge`** - `transfer()` in L1059 - `approve()` in L1077 - `transferFrom()` in L1086 - `increaseAllowance()` in L1103 - `decreaseAllowance()` in L1116 - `deliver()` in L1144 - `excludeFromReward()` in L1256 - `excludeFromFee()` in L1278 - `includeInFee()` in L1282 - `excludeFromLimit()` in L1286 - `includeInLimit()` in L1290 - `setSwapAndLiquifyEnabled()` in L1363
The constant state variable `_decimals`, in #L941, does not be used at the linked statements.
The definition type of `buyFee` and `sellFee` is `uint8`, and contract-related operations use `uint256` to receive calculation results.
The transaction may be charged fees, so the max holding of receiver should be `balanceOf(to) + transferAmount`. The fees should not be calculated in the max holding.
The function that affects the status of sensitive variables should be able to emit events as notifications to customers. **contract `ShibaDoge`** - `deliver()` - `updateMarketingWallet()` - `updateDevWallet()` - `updateExchangeWallet()` - `updatePartnershipsWallet()` - `addBotToBlacklist()` - `removeBotFromBlacklist()` - `excludeFromReward()` - `includeInReward()` - `excludeFromFee()` - `includeInFee()` - `excludeFromLimit()` - `includeInLimit()` - `setSellFee()` - `setBuyFee()` - `setBothFees()` - `setNumTokensSellToAddToLiquidity()` - `setMaxTxPercent()` - `_setMaxWalletSizePercent()`
The given input is missing the sanity check.
After the deployment of the contract, the fee of buying or selling is up to 95%. Additionally, all fees can be set by the owner.
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 being attacked) a transaction to purchase one of the assets and make profits by backrunning (after the transaction being 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: - `swapTokensForEth()` - `addLiquidity()`
When `swapAndLiquify()` is invoked, a portion of fees will be added as liquidity to the corresponding pool and the rest will be sent to `_marketingAddress` and `_devwallet`. The contract applies comprehensive mathematics to divide those fees, which could lead to an inaccurate result due to rounding error. Considering the complexity of the transactions on-chain, it is recommended to use a more simple/robust algorithm to divide the fees.
The condition `!_isExcluded[sender] && !_isExcluded[recipient]` can be included in `else` .
The return values of function `addLiquidityETH` are not properly handled. ```solidity=1679 uniswapV2Router.addLiquidityETH{value: ethAmount}( address(this), tokenAmount, 0, // slippage is unavoidable 0, // slippage is unavoidable address(this), block.timestamp ); ```
The function `deliver()` can be called by anyone. It accepts an uint256 number parameter `tAmount`. The function reduces the token balance of the caller by `rAmount`, which is `tAmount` reduces the transaction fee. Then, the function adds `tAmount` to variable `_tFeeTotal`, which represents the contract's total transaction fee.
The scope of the audit treats 3rd party entities as black boxes and assumes their functional correctness. However, in the real world, 3rd parties can be compromised and this may lead to lost or stolen assets. In addition, upgrades of 3rd parties can possibly create severe impacts, such as increasing fees of 3rd parties, migrating to new LP pools, etc.
`recieve` should be `receive` in the line of comment `//to recieve ETH from uniswapV2Router when swapping`.
The following contracts have unlocked compiler versions. An unlocked compiler version in the source code of the contract permits the user to compile it at or above a particular version. This, in turn, leads to differences in the generated bytecode between compilations due to differing compiler version numbers. This can lead to ambiguity when debugging as compiler specific bugs may occur in the codebase that would be difficult to identify over a span of multiple compiler versions rather than a specific one. - ShibaDoge.sol
The following events are declared but never used: - `botAddedToBlacklist` - `botRemovedFromBlacklist` - `MinTokensBeforeSwapUpdated` - `SwapAndLiquify`
Variables `_tTotal`, `_name`, `_symbol` and `_decimals` could be declared as `constant` since these state variables are never to be changed.
| Address | Chain | Source code |
|---|---|---|
| 0x6adb…928f0x6adb2e268de2aa1abf6578e4a8119b960e02928f | Chain: Ethereum | Source code: Verified source |
1,044 projects reviewed · 1,393 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