FlokiFi security record

Arbitrum, Avalanche, Base, Blast, BNB Chain, Ethereum, Fantom, Optimism, Polygon (POS)flokifi.comXGitHub

As of 3 Nov 2026, FlokiFi has 3 audit reports by 1 security firm on Trustblock; the latest is by CertiK, dated 6 Nov 2023. Those reports list no open critical findings.

Critical findings
No open critical findings
Across 3 reports.
Open the latest report
Your label, live
Get the label for your site

Record last updated . It holds audits, findings and contracts up to Nov 2026, and incidents up to Oct 2026. Trustblock does not review code.

Audits3

Newest first

AuditSecurity firmDateScopeCritical findingsReport
Flokifi StakingSecurity firm: CertiKDate: Scope: Files named in the reportNo open critical findingsOpen · skynet.certik.com
Flokifi IISecurity firm: CertiKDate: Scope: Files named in the reportNo open critical findingsOpen · skynet.certik.com
FlokifiSecurity firm: CertiKDate: Scope: Files named in the reportNo open critical findingsOpen · skynet.certik.com

Findings48

Statuses are the security firm’s own, from each report.

SeverityOpenAcknowledgedFixed
Critical000
High605
Medium005
Low6026
HighCentralization Risks in FlokiRewardToken.solFlokifi Staking · CertiK · 6 Nov 2023Fixed

In the contract `FlokiRewardToken` the role `DEFAULT_ADMIN_ROLE` has authority over the functions shown in the diagram below. Any compromise to the `DEFAULT_ADMIN_ROLE` account may allow the hacker to take advantage of this authority and mint arbitrary amounts of tokens. ![](https://accelerator-tasks-prod.acc.corp.certik.com/11ee-46da-a85e47f0-ae27-63b6532b39b9/diagrams/centralization_FlokiRewardToken-FlokiRewardToken-DEFAULT_ADMIN_ROLE.svg)

Open the report
High`_lastAdded` not updatedFlokifi · CertiK · 14 Mar 2023Fixed

The private variable `_lastAdded` has not been updated anywhere, hence `_lastAdded[lpToken]` will always be zero, as a result, the `_sellDelay` check will be easily passed.

Open the report
HighLack of Fallback or Receive Function When ReceiviFlokifi · CertiK · 14 Mar 2023Fixed

The common UniswapV2 functionality allows contracts to swap tokens for a native token such as ETH. In order to receive the native token, the contract must implement either a `receive()` or `payable fallback` function. If the contract's Solidity version is below 0.6.x, the contract must implement an unnamed payable function.

Open the report
HighSome `_lpTokens` may never in the `tokenBatch`Flokifi · CertiK · 14 Mar 2023Fixed

According to the following code: ```solidity function checkUpkeep( bytes memory /* checkData */ ) external view override returns (bool upkeepNeeded, bytes memory performData) { ... uint256 loopLimit = _lpTokens.length(); if (loopLimit > _maxSellBatchSize) { loopLimit = _maxSellBatchSize; } address[] memory tokenBatch = new address[](loopLimit); uint256 tokenBatchCounter = 0; for (uint256 i = 0; i < loopLimit; i++) { address lpToken = _lpTokens.at(i); if ((_lastAdded[lpToken] + _sellDelay) < block.timestamp) { tokenBatch[tokenBatchCounter] = lpToken; } } ... } ``` , if the length of `_lpTokens` is 30, while the `_maxSellBatchSize` is 20, then the `loopLimit` will be 20. In this case, the number from 20 to 29 of `_lpTokens` will never be added to the `tokenBatch` no matter how many times the `checkUpkeep()` is called.

Open the report
HighThe `performData` should not be manually passedFlokifi · CertiK · 14 Mar 2023Fixed

The function `performUpkeep()` should perform the _removeLiquidity() for the LP tokens in the LPTokenProcessorV1 contract. However, this function takes the parameter `performData` as the target. The truth is the LP token in the parameter `performData` may not exist in the LPTokenProcessorV1 contract.

Open the report
MediumLack of sanity check in function `stake`Flokifi Staking · CertiK · 6 Nov 2023Fixed

The function `stake()` does not check the `_minimumStakeTimestamp` not greater than the `endsAt`. Then there will be a period after `endsAt` with no rewards. However, when the user unstakes before `_minimumStakeTimestamp` the user will pay a penalty fee.

Open the report
MediumMissing update in the function `extendStake`Flokifi Staking · CertiK · 6 Nov 2023Fixed

When the user calls the extendStake function, the duration will be changed, which means the duration multiplier should be changed as well. However, there is no update of unstakeTimestamp in this function.

Open the report
Medium`keyId` may be equal to 0Flokifi II · CertiK · 8 Oct 2023Fixed

The `createVaultWithoutKey()` function can be called by someone in the whitelist to create a vault, but does not mint nft, so `IVault(vault).vaultKeyId()` always returns 0 when called within the function `createVaultWithoutKey`, and the variable `vaultByKey[keyId]` will be overwritten.

Open the report
MediumThe `tokenBatchCounter` should be addedFlokifi · CertiK · 14 Mar 2023Fixed

According to the following code: ```solidity function checkUpkeep( ... address[] memory tokenBatch = new address[](loopLimit); uint256 tokenBatchCounter = 0; for (uint256 i = 0; i < loopLimit; i++) { address lpToken = _lpTokens.at(i); if ((_lastAdded[lpToken] + _sellDelay) < block.timestamp) { tokenBatch[tokenBatchCounter] = lpToken; } } ``` , the `tokenBatchCounter` should be added after `tokenBatch[tokenBatchCounter] = lpToken`.

Open the report
MediumWrong calculation in `getAvailableTokens()`Flokifi · CertiK · 14 Mar 2023Fixed

According to the following code, ```solidity function getAvailableTokens() public view returns (address[] memory, uint256[] memory) { ... // Send over all remaining tokens in the case where the unlock // timestamp has already expired. Otherwise vest linearly. if (block.timestamp >= unlockTimestamp) { amounts[i] = IERC20(tokens[i]).balanceOf(address(this)); } else { amounts[i] = (tokenAmounts[i] * (block.timestamp - lastVestingTimestamp)) / (unlockTimestamp - lockTimestamp); ... } ``` , when `block.timestamp < unlockTimestamp`, the `amounts[i]` will be calculated linearly in terms of the `block.timestamp - lastVestingTimestamp`, however, according to the contract `PaymentModuleV1`, when the token is a LP token, the amount of tokens deposited in the contract should be `fungibleTokenDeposits[i].amount - lpAmounts[j]` instead of the `tokenAmounts[i]`.

Open the report
Show 10 more
LowIncorrect change of isPausedFlokifi Staking · CertiK · 6 Nov 2023Fixed

The function pauseStaking incorrectly change the state of `isPaused`.

Open the report
LowLack of reasonable boundaryFlokifi Staking · CertiK · 6 Nov 2023Fixed

In the constructor of the PenaltyFee contract, the `penaltyBasis` will be set by the parameter and it can be close to the MULTIPLIER_BASIS. Hence the `penaltyFee` can be bigger than the stake amount which is unreasonable.

Open the report
LowLogical issue in extendRewardsDurationFlokifi Staking · CertiK · 6 Nov 2023Fixed

In the function `extendRewardsDuration()`, the extended duration will be added to the old duration, the endsAt will be delayed for the extended duration as well. So this function needs to be called immediately after the old duration is over.

Open the report
LowMissing base digit in the use of decimalFlokifi Staking · CertiK · 6 Nov 2023Fixed

In the functions `getUserRewards()` and `rewardPerToken()`, the calculation uses the decimal to avoid the divide truncation issue. However, the base digit of the multiplication is missing in the calculation.

Open the report
LowNo reward in `setStakingDuration`Flokifi Staking · CertiK · 6 Nov 2023Fixed

When the function `setStakingDuration` is called, no previous reward tokens are left since the previous duration is over. However, there is no new reward tokens transferred in the contract. The similar issue is existing in the function `extendRewardsDuration`.

Open the report
LowRedundant comparisonFlokifi Staking · CertiK · 6 Nov 2023Fixed

In the function `lastTimeRewardApplicableForUser`, the code logic will check whether the `block.timestamp` is greater than the unstakeTimestamp[_user]. If yes, it will directly return the unstakeTimestamp[_user]. If not, it means `block.timestamp` is not greater than the unstakeTimestamp[_user]. Since the _unstakeTimestamp must be not greater than endsAt which is restricted when staking, so the `block.timestamp` must be smaller than endsAt. ```solidity function lastTimeRewardApplicableForUser(address _user) public view returns (uint256) { if (block.timestamp > unstakeTimestamp[_user]) { return unstakeTimestamp[_user]; } return block.timestamp < endsAt ? block.timestamp : endsAt; } ```

Open the report
LowThird-Party DependenciesFlokifi Staking · CertiK · 6 Nov 2023Fixed

The contract is serving as the underlying entity to interact with third-party `stakingToken`. 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. ```solidity=127 stakingToken.safeTransferFrom(msg.sender, address(this), _amount); ```

Open the report
LowIncompatibility with Deflationary TokensFlokifi II · CertiK · 8 Oct 2023Fixed

When transferring deflationary ERC20 tokens, the input amount may not be equal to the received amount due to the charged transaction fee. For example, if a user sends 100 deflationary tokens (with a 10% transaction fee), only 90 tokens actually arrived to the contract. However, a failure to discount such fees may allow the same user to withdraw 100 tokens from the contract, which causes the contract to lose 10 tokens in such a transaction. Reference: https://thoreum-finance.medium.com/what-exploit-happened-today-for-gocerberus-and-garuda-also-for-lokum-ybear-piggy-caramelswap-3943ee23a39f ```solidity=241 USDT.safeTransferFrom(user, address(this), usdtAmount); ``` - Transferring tokens by `usdtAmount`. ```solidity=263 uint256 treasuryUSDTShare = usdtAmount - referrerUSDTShare - burnShare; ``` - The `usdtAmount` appears to be used for bookkeeping purposes without compensating the potential transfer fees.

Open the report
LowPotential exemption from chargesFlokifi II · CertiK · 8 Oct 2023Fixed

The `_hasDiscount` function is called to check if it owns a certain nft that can be discounted, so there may be some sort of nft supported by this contract that can be used for borrowing, and therefore the user can be exempted from the charge by borrowing the nft.

Open the report
LowPotential Incorrect ChecksFlokifi II · CertiK · 8 Oct 2023Fixed

The function `isV2LiquidityPoolToken()` is designed to check if the passed-in address token is an uniswap v2 pair, the function's checking is lax, and a malicious user can build a contract to pass the check, as is the case with the `isV3LiquidityPoolToken` function.

Open the report
Show 10 more
LowPotential Removal FailsFlokifi II · CertiK · 8 Oct 2023Fixed

The `removeTokensFromSwappingByIndexes()` function is called to remove the addresses of the tokens at the specified locations. Since the removal is cyclic, it is possible that the incoming locations have already been removed and the function call will fail. ```solidity=141 address tokenAddress = _tokens[index].tokenAddress; _tokens[index] = _tokens[_tokens.length - 1]; _tokens.pop(); ```

Open the report
LowPotential Sandwich AttacksFlokifi II · CertiK · 8 Oct 2023Fixed

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: - `router.removeLiquidity()` - `router.swapExactTokensForTokens()`

Open the report
LowPotential tokens are locked to the contractFlokifi II · CertiK · 8 Oct 2023Fixed

The `reinvestV3PositionFees()` can be called by the owner of the vault to collect the LP fee and transfer the fee tokens to the current vault, then this part of the token to increase liquidity. ```solidity IERC20(token0).safeApprove(address(tokenAddress), earnedToken0); IERC20(token1).safeApprove(address(tokenAddress), earnedToken1); INonfungiblePositionManager.IncreaseLiquidityParams memory params = INonfungiblePositionManager.IncreaseLiquidityParams({ tokenId: tokenId, amount0Desired: earnedToken0, amount1Desired: earnedToken1, amount0Min: amount0Min, amount1Min: amount1Min, deadline: block.timestamp }); INonfungiblePositionManager(tokenAddress).increaseLiquidity(params); ``` The function `increaseLiquidity()` returns the amount of tokens used to add liquidity, and the parameter `earnedToken` may not necessarily be equal. As a result, there is a possibility that some tokens will remain in the contract. If these tokens are not present in `fungibleTokenDeposits`, then this portion of tokens will be locked in the contract.

Open the report
LowThe token received by the `lpTokenProcessor` mayFlokifi II · CertiK · 8 Oct 2023Fixed

The function `_processNfts` is called to remove liquidity and collect fees and then transfer the asset to the `lpTokenProcessor` for processing. The token accepted by the `lpTokenProcessor` should be equal to the difference between before and after the transfer. ```solidity=161 IERC20(price.v3LpTokens[i].token0).safeTransfer(address(lpTokenProcessor), balance0); IERC20(price.v3LpTokens[i].token1).safeTransfer(address(lpTokenProcessor), balance1); uint256 amount0Received = initialToken0Balance - IERC20(price.v3LpTokens[i].token0).balanceOf(address(this)); uint256 amount1Received = initialToken1Balance - IERC20(price.v3LpTokens[i].token1).balanceOf(address(this)); ```

Open the report
LowUnused ValueFlokifi II · CertiK · 8 Oct 2023Fixed

The smart contract contains one or more values that are not used, which can lead to unnecessary complexity and reduced maintainability. ```solidity=105 uint256 referrerLPShare = 0; ``` - The variable `referrerLPShare` is never used after this assignment. --- ```solidity=107 referrerLPShare = (price.v2LpAmounts[i] * referrerBasisPoints) / 10000; ``` - The variable `referrerLPShare` is never used after this assignment. --- ```solidity=226 uint256 usdBalance = usdtAmount; ``` - The variable `usdBalance` is never used after this assignment. --- ```solidity=211 try discountNFTs[i].tokenOfOwnerByIndex(user, 0) returns (uint256) { return true; } catch ( bytes memory /* lowLevelData */ ) {} ``` - The variable `` is never used after this assignment.

Open the report
LowAssembly UsageFlokifi · CertiK · 14 Mar 2023Fixed

```solidity=161 assembly { mstore(paymentTokens, sub(mload(paymentTokens), sub(totalTokens, paymentCounter))) mstore(paymentAmounts, sub(mload(paymentAmounts), sub(totalTokens, paymentCounter))) } ```

Open the report
LowMissing Emit EventsFlokifi · CertiK · 14 Mar 2023Fixed

There should always be events emitted in the sensitive functions that are controlled by centralization roles.

Open the report
LowMissing Error MessagesFlokifi · CertiK · 14 Mar 2023Fixed

The **require** can be used to check for conditions and throw an exception if the condition is not met. It is better to provide a string message containing details about the error that will be passed back to the caller.

Open the report
LowMissing Zero Address ValidationFlokifi · CertiK · 14 Mar 2023Fixed

Addresses should be checked before assignment or external call to make sure they are not zero addresses. ```solidity=15 vaultFactory = vaultFactoryAddress; ``` - `vaultFactoryAddress` is not zero-checked before being used. --- ```solidity=43 USDT = usdtAddress; ``` - `usdtAddress` is not zero-checked before being used. --- ```solidity=38 FLOKI = flokiAddress; ``` - `flokiAddress` is not zero-checked before being used. --- ```solidity=42 treasury = treasuryAddress; ``` - `treasuryAddress` is not zero-checked before being used. --- ```solidity=169 treasury = newTreasury; ``` - `newTreasury` is not zero-checked before being used.

Open the report
LowPrivileges on the `KeyHolder` roleFlokifi · CertiK · 14 Mar 2023Fixed

The role 'KeyHolder' has lots of privileges to control the corresponding vault, we would like the client to provide with us more information about the 'KeyHolder' role.

Open the report
Show 6 more
LowRedundant `oldPrice` and `oldBasisPoints`Flokifi · CertiK · 14 Mar 2023Fixed

The local variable `oldPrice` and `oldBasisPoints` are defined but not used anywhere in the function, hence they are redundant.

Open the report
LowSending Ether to Arbitrary DestinationsFlokifi · CertiK · 14 Mar 2023Fixed

The function call that sends Ether to an arbitrary address is unprotected. ```solidity=264 try router.swapExactETHForTokens{ value: ETHGained }(0, path, receiver, block.timestamp) returns ( uint256[] memory /* amounts */ ) {} catch ( bytes memory /* lowLevelData */ ) { return false; } ```

Open the report
LowUnchecked ERC-20 `transfer()`/`transferFrom()` CaFlokifi · CertiK · 14 Mar 2023Fixed

The return value of the transfer()/transferFrom() call is not checked. ```solidity=27 token.transferFrom(address(this), msg.sender, token.balanceOf(address(this))); ``` --- ```solidity=34 IERC20(_tokenAddress).transferFrom(address(this), msg.sender, _tokenAmount); ``` --- ```solidity=40 token.transferFrom(address(this), msg.sender, token.balanceOf(address(this))); ``` --- ```solidity=69 IERC20(_tokenAddress).transferFrom(address(this), msg.sender, _tokenAmount); ```

Open the report
LowUnchecked Low-level CallFlokifi · CertiK · 14 Mar 2023Fixed

The low-level `call` function returns the status of the call as the first variable in the returned tuple. The status of the `call` is not asserted to be `true`, which would treat the low-level call as a success even when it reverted. ```solidity=201 payable(msg.sender).call{value: amount}(""); ```

Open the report
LowUnused EventFlokifi · CertiK · 14 Mar 2023Fixed

```solidity=31 event LPTokenCleared(address indexed tokenAddress); ``` - `LPTokenCleared` is declared in `LPTokenProcessorV1` but never emitted.

Open the report
LowVariables That Could Be Declared as ImmutableFlokifi · CertiK · 14 Mar 2023Fixed

The linked variables assigned in the constructor can be declared as `immutable`. Immutable state variables can be assigned during contract creation but will remain constant throughout the lifetime of a deployed contract. A big advantage of immutable variables is that reading them is significantly cheaper than reading from regular state variables since they will not be stored in storage.

Open the report

Contracts

No deployed address is recorded for these audits.

The reports name a repository or files. Open a report to see its scope.

The repositories and files the reports name

Show this on your site

Is this your project? Show this record on your own website. The label states what the record holds, links to this page and updates by itself. It is free and needs no sign-in.

Content

Facts

Automatic: the three strongest facts of this project’s own record (its last audit and two more), highlighted. They update with the record. Picking a fact turns Automatic off.

Fixed as
Language

Style

Layout
Theme
Accent
Corners

Format

Size
Date
Embed as
HTML
<head>
<script src="https://widget.trustblock.run/project-widget.min.js" defer></script>
</head>
<body>
<div
data-tb-project-widget
data-tb-project-slug="flokifi"
></div>
</body>

Paste the code where the label should appear. It uses no API credit and updates by itself.

Something 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