KODA token smart contract audit report
HashEx was commissioned by the Koda Cryptocurrency team to perform an audit of their smart contracts. The audit was conducted between September 20 and September 21, 2021.
The audited code was provided directly in .sol files without any documentation or tests.
The purpose of this audit was to achieve the following:
- Identify potential security issues with smart contracts.
- Formally check the logic behind given smart contracts.
Information in this report should be used to understand the risk exposure of smart contracts, and as a guide to improving the security posture of smart contracts by remediating the issues that were identified.
We found out that the KODA token is based on Reflect.finance [1] with an audit report available [2].
Update: the updated code was deployed to the Binance Smart Chain (BSC):
0x8094e772fA4A60bdEb1DfEC56AB040e17DD608D5.
Contracts overview
KODA
Implementation of ERC20 token standard [5] with the custom functionality of auto-yield by burning tokens and distributing the fees on transfers. Fees are distributed between users (default value 2%) and sent to EOA (default value 8%).
Ownable
A modified version of OpenZeppelin’s contract with temporary renounce functionality.
Found issues
#01 No limits in reduceBuyFee(): High severity
The reduceBuyFee()
function in L945 doesn’t perform any checks on the input value of the buyFeeReductionPercentage
variable and could be set way above 100% blocking all the transfers from the swap pair. Once called, the buyFeeReduced
boolean variable can’t be reverted to false, buyFeeReducedTime
is not used.
Recommendation: refactor the buyFeeReduction functionality from scratch.
Update: the issue was fixed.
#02 _takeLiquidity() recipient: Medium severity
Unlike the SafeMoon token, KODA contract doesn’t implement the auto liquify feature but sends the liquidity fee of 8% (default value, up to 10%) to the _kodaLiquidityProviderAddress
account with unclear ownership. The setKodaLiquidityProviderAddress()
function allows the owner to change the recipient of the liquidity fee to any address.
Team response: The setKodaLiquidityProviderAddress
function is to allow us to change the contract that manages the fee. The fee that is sent to this is fixed at a maximum of 10% regardless, (Reflections plus fee must be equal to or less than 10%). We need the ability to change this provider address in case of upgrading the fee manager contract in the future. This would then alleviate the need to migrate to another version of Koda.
#03 setMaxTxnTokens() wrong limit: Medium severity
setMaxTxnTokens()
function in L930 checks the maximum valid input value but updates the _maxTxnAmount
variable with input value multiplied by 10^decimals.
Update: the issue was fixed. The transaction limit was removed completely.
#04 Prohibited transfers from/to dEaD address: Medium severity
_approve()
and _transfer()
functions check the input addresses to not be equal to 0xdEaD burn address instead of zero to prevent accidentally locked tokens.
Also, transfer functions of the reviewed contract don’t throw error messages for the amounts bigger than the sender’s balance (like “ERC20: transfer amount exceeds allowance” in OpenZeppelin’s ERC20 implementation) which may confuse users.
Update: the issue was fixed.
#05 Fee pause not working with pair transfers: Medium severity
transferFeePaused boolean variable doesn’t work for transfers from or to swap pair, see L1106–1107.
Update: the issue was fixed.
#06 Unused parameters & imports: Low severity
buyFeeReducedTime
, summitSwapRouter
, _burnAddress
variables aren’t in use.
ISummitSwapRouter02
, ISummitSwapRouter01
, ISummitSwapPair
, ISummitSwapFactory
interfaces aren’t in use.
SafeMath library should be removed or updated to the 0.4 release version.
Update: the issue was fixed.
#07 Missing events: Low severity
There’re zero custom events implemented. We recommend emitting a specific event every time the system parameter is updated.
Team response: we’ve decided against implementing this.
#08 Unreachable code: Low severity
The _tokenTransfer()
function contains an unreachable condition in L1135.
Update: the issue was fixed.
#09 Incorrect error message: Low severity
Incorrect error message in L875: the message should be “Account is already included”.
Update: the issue was fixed.
#10 Inconsistent comments & typos: Low severity
TODO comments L1, L700. Inconsistent comments in L704, L1091. Typos in L727, 729, 732, 797,918, 927, 962, 1015, 1038, 1143, 1160, 1177.
Update: the issue was fixed.
#11 General recommendations: Low severity
The code is ineffective in terms of computational costs. For example, removeAllFee()
and restoreAllFee()
functions write 6 variables to free a transfer from fees. While this is not a big deal in BSC, the code should be refactored before possible deployment to the Ethereum mainnet.
We recommend fixing the pragma version to avoid discrepancies in contract behavior compiled with different Solidity versions.
We discourage changing well-tested libraries contracts such as the Ownable contract from OpenZeppelin. The additional functionality should be implemented via inheritance. SafeMath should be updated to the corresponding release to save gas on unnecessary checks.
Conclusion
The audited contract is a fork of Reflect.finance smart contract with some changes.
1 high severity and 4 medium severity issues were found.
The contract, which implies high risks for token holders as if the owner account is compromised an attacker can break the token functionality completely (for example, by blocking any transfer).
Audit includes recommendations on the code improving and preventing potential attacks.
Update: most of the issues were fixed including the High severity one. The updated code was deployed to the Binance Smart Chain (BSC):
0x8094e772fA4A60bdEb1DfEC56AB040e17DD608D5.
References
HashEx website: https://hashex.org
Request an audit