Rhino.sol

Issue 01

Description

10 ** 18 is a standard unit in solidity, and has a special keyword "ether".

Recommendation

Consider using ether instead of 10**18 for readability.

Issue 02

Description

In order to prevent the contract from receiving ETH from investors, which will result in a loss of funds, our recommendation is to have “whitelisted” addresses which can send ETH to the contract (for example the router address should be whitelisted).

When an investor sends ETH by mistake, the transaction will be reverted by the contract.

Issue 03

Description

The owner of the contract can set the buy fee and sell fee by calling setLiquiditFee or setMarketingFee , setBurnFee , setDOTRewardsFee to any value he desires. If the owner sets the fee to 100% the token will be untradeable.

Recommendation

Consider adding maximum value for these set functions and consider adding limitation to the sum of all the fees.

The team fixed this issue, and now the total fees are limited to 40%.

Issue 04

Description

The owner of the contract can call setMaxSellTxAmount with 0, and make the token unsellable.

Recommendation

Consider making the max sell amount be in percentage of the circulating supply.

Issue 05

Description

The set functions don't emit events.

Recommendation

Consider adding events when changing critical variables or the state of the contract.

Issue 06

Description

isExcludedFromFees could have been declared as external to save on gas fees.

Issue 07

Description

_transfer may call internally to swapExactTokensForETHSupportingFeeOnTransferTokens, addLiquidityETHand swapExactTokensForTokensSupportingFeeOnTransferTokens which may cause _transfer to fail unnecessarily.

Recommendation

_transfer should always work, and shouldn't fail if swapExactTokensForETHSupportingFeeOnTransferTokens or addLiquidityETH fails in order to make sure the token will always be tradable.

Issue 08

Description

The code doesn’t differentiate between sell transaction and addLiquidity transaction (because the user sends tokens to the pair). Therefore, maxSellTransactionAmount limitation will be also applied for people who adds liquidity.

Issue 09

Description

swapTokensAtAmount is the number of tokens that will be sold by the contract as part of the automatic liquidity addition mechanism. At the moment it is set to 200000 tokens. The team needs to acknowledge that the price impact every time swap and liquify will take place is determines by the amount of tokens in the pool. The team needs to monitor the value of swapTokensAtAmount in order to make sure the price impact is not too large.

Issue 10

Description

newBalance will always be 0, and therefore addLiquidity will always be called with 0 BNB.

function swapAndLiquify(uint256 tokens) private {
       // split the contract balance into thirds
        uint256 halfOfLiquify = tokens.div(4);
        uint256 otherHalfOfLiquify = tokens.div(4);
        uint256 portionForFees = tokens.sub(halfOfLiquify).sub(otherHalfOfLiquify);

        // capture the contract's current ETH balance.
        // this is so that we can capture exactly the amount of ETH that the
        // swap creates, and not make the liquidity event include any ETH that
        // has been manually sent to the contract
        uint256 initialBalance = address(this).balance;
        uint256 newBalance = address(this).balance.sub(initialBalance);

Recommendation

newBalance should be calculated after calling swapTokensForEth.

Issue 11

Description

Approve is being called every transaction on the same tokens and for the same spender (the router).

Recommendation

In order to reduce gas costs, approve could be called once (with max int), and then check if it is needed again using allowance.

Issue 12

Description

The contract may call swapExactTokensForETHSupportingFeeOnTransferTokens twice, each swapExactTokensForETHSupportingFeeOnTransferTokens consumes a large amount of gas.

Recommendation

Consider calling swapExactTokensForETHSupportingFeeOnTransferTokens only once.

Issue 13

Description

This function sends all the BNB in the contract to a marketing wallet, instead of only the BNB allocated for marketing.

Issue 14

Description

The recipient of the newly created LP tokens is the owner of the contract. The newly created LP tokens are unlocked.

   // add the liquidity
        uniswapV2Router.addLiquidityETH{value: ethAmount}(
            address(this),
            tokenAmount,
            0, // slippage is unavoidable
            0, // slippage is unavoidable
            owner(),
            block.timestamp
        );

Recommendation

Our recommendation is to change the recipient of the newly created LP tokens to the contract in order to ensure that the LP tokens are locked or to simply locked the tokens in the contract for a certain period.

Issue 15

Description

_transfer may call distributeDOTDividends internally, Since this function can be called during _transfer, which may cause it to fail unnecessarily when totalSupply of DividendPayingToken is 0.

Recommendation

Consider using try-catch when calling distributeDOTDividends

Issue 16

Description

If the dividends token has fees on transfer, the code may not work correctly since the dividends contract will receive fewer tokens than expected and the rewards won't be calculated correctly.

Recommendation

Consider adding general support for dividends tokens with fees on transfer.

Issue 17

Description

The swapAndLiquify function converts half of the contract’s tokens to BNB. The other half of the tokens are used for liquidity addition. The price of the token drops after executing the first conversion, having said that the other half of tokens require less than the converted BNB to be paired with it when adding liquidity.

Recommendation

Consider using the leftover bnb for buyback.

Issue 18

Description

withdrawDividend will always fail.

Recommendation

Consider using revert instead of require.

Issue 19

Description

swapAndSendDividends will fail if totalSupply of DividendPayingToken is 0, the dividends sent to the contract will be stuck and won't be used for rewards.

Recommendation

Consider handling a scenario in which totalSupply is 0, and dividends are transferred to the contract.

Last updated