CertiK reviewed TokenFi on 31 Oct 2023: 10 findings, 0 critical; 2 marked fixed, 8 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 | 3 | 0 | 0 |
| Medium | 1 | 0 | 0 |
| Low | 4 | 0 | 2 |
In the contract `FLOKI` 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. - The function `setTreasuryHandler` to set the `treasuryHandler`. - The function `setTaxHandler` to set the `taxHandler`. Note that the token transfer functions may revert if these addresses are incorrectly set.  In the contract `Tokenfi` 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. - The function `withdraw` to send any tokens or ETH stuck in the token contract to the treasury handler. - The function `setTreasuryHandler` to set `treasuryHandler`. - The function `setTaxHandler` to set `taxHandler`. Note that the token transfer functions may revert if these addresses are incorrectly set.  In the contract `ExponentialTaxHandler` 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. The functions addExemption/removeExemption can be used to add/remove addresses from the `_exempted` address set.  In the contract `StaticTaxHandler` 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. - The function `setTaxBasisPoints` can be used to set `taxBasisPoints`. - The functions `addExemption/removeExemption` can be used to add/remove addresses from the `_exempted` address set.  In the contract `ExchangePoolProcessor` 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. - The functions `addExchangePool/removeExchangePool` can be used to add/remove pool addresses from the `_exchangePools` address set. - The function `setPrimaryPool` can be used to set `primaryPool`.  In the contract `TreasuryHandlerAlpha` 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. - The function `withdraw` can be used to withdraw any tokens or ETH in the treasury handler to the treasury EOA address. - The function `setPriceImpactBasisPoints` can be used to set `priceImpactBasisPoints`. - The function `setTreasury` can be used to set `treasury`. - The function `setLiquidityBasisPoints` can be used to set `liquidityBasisPoints`. 
In the contracts `FLOCKI` and `Tokenfi`, taxes collected by the `treasuryHandler` are partially used to add liquidity, resulting in the LP tokens being transferred to the `treasury` address. Over time, this design will lead to an increasing centralization of LP tokens within the `treasury` address. Any compromise to the private key of the `treasury` address may allow a hacker to take advantage of the EOA address authority and remove the liquidity from the pool. This could have devastating consequences for the entire project.
All of the FLOKI tokens and Tokenfi tokens are sent to the contract deployers. This is a centralization risk because the deployers can distribute tokens without obtaining the consensus of the community. Any compromise to these addresses may allow a hacker to steal and sell tokens on the market, resulting in severe damage to the project.
The `setTaxBasisPoints()` function allows the `_owner` to modify the `taxBasisPoints`, which determines the fee percentage. While there is a cap set at 4,000 basis points (equivalent to 40%), such a high fee rate could be unreasonably high for users. ```solidity function setTaxBasisPoints(uint256 newBasisPoints) external onlyOwner { require( newBasisPoints <= 4000, "StaticTaxHandler:setTaxBasisPoints:HIGHER_VALUE: Basis points cannot exceed 4,000." ); uint256 oldBasisPoints = taxBasisPoints; taxBasisPoints = newBasisPoints; emit TaxBasisPointsUpdated(oldBasisPoints, newBasisPoints); } ```
The function `transferFrom()` in an ERC20 contract is used in the above-mentioned contracts to receive the user payments to the contract. When the contract needs to transfer assets out, it is better to use the function `transfer()/safeTransfer()` because it is possible that the target `tokenAddress` does not support transfer from the user itself. ```solidity=343 function withdraw(address tokenAddress, uint256 amount) external onlyOwner { if (tokenAddress == address(0)) { payable(address(treasuryHandler)).sendValue(amount); } else { IERC20(tokenAddress).transferFrom(address(this), address(treasuryHandler), amount); } } ``` If the contract uses `transferFrom()` to transfer the ERC20 token from itself, and it has no approvals, it may revert transactions.
In a front-running attack, an attacker identifies a pending transaction on the public blockchain and jumps ahead of it (typically by paying higher gas fees). A sandwich attack is a specialized form of front-running. In this scenario, attackers identify users making token swaps or adding liquidity without appropriate slippage limits. The attacker then profits by buying the asset before the victim's transaction and selling it immediately afterwards. 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: ```solidity=234 router.swapExactTokensForETHSupportingFeeOnTransferTokens(tokenAmount, 0, path, address(this), block.timestamp); ``` ```solidity=247 router.addLiquidityETH{ value: weiAmount }( address(token), tokenAmount, 0, 0, address(treasury), block.timestamp ); ```
The contract is serving as the underlying entity to interact with one or more third party protocols. The scope of the audit treats third party entities as black boxes and assumes their functional correctness. However, in the real world, third parties can be compromised and this may lead to lost or stolen assets. In addition, upgrades of third parties can possibly create severe impacts, such as increasing fees of third parties, migrating to new LP pools, etc. ```solidity=35 IUniswapV2Router02 public router; ``` - The contract `TreasuryHandlerAlpha` interacts with third party contract with `IUniswapV2Router02` interface via `router`.
The `withdraw()` function is designed to allow the `_owner` to withdraw locked Ether or ERC20 tokens. However, the contract lacks any `payable` or `receive()` function, making it incapable of holding or receiving Ether. ```solidity=339 function withdraw(address tokenAddress, uint256 amount) external onlyOwner { if (tokenAddress == address(0)) { payable(address(treasuryHandler)).sendValue(amount); } else { IERC20(tokenAddress).transferFrom(address(this), address(treasuryHandler), amount); } } ```
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (12)
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