YieldFlow security record

Ethereum, Polygon (POS)yieldflow.comXGitHub

As of 3 Nov 2026, YieldFlow has 2 audit reports by 1 security firm on Trustblock; the latest is by CertiK, dated 12 Apr 2024. Those reports list no open critical findings.

Critical findings
No open critical findings
Across the 2 reports, 3 critical findings were reported. Each is marked fixed by the firm that reported it. See the findings
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.

Audits2

Newest first

AuditSecurity firmDateScopeCritical findingsReport
YieldFlow - Audit 2Security firm: CertiKDate: Scope: Files named in the report3 critical findings, fixedOpen · skynet.certik.com
YieldFlowSecurity firm: CertiKDate: Scope: Files named in the reportNo open critical findingsOpen · skynet.certik.com

Findings63

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

SeverityOpenAcknowledgedFixed
Critical003
High103
Medium0010
Low1045
CriticalIssues If NFT's Are Minted Or Burned Between DistYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

If new NFTs are minted and sold after fees are distributed, but before they are claimed, an exploiter could purchase a new NFT and claim fees that another user was entitled to. There are also issues if an NFT is burned before fees are claimed, as any unclaimed fees may be locked in the contract.

Open the report
CriticalNFTs Can Be Transferred To Repeatedly Claim FeesYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

Fees are distributed according to the NFT balance of the holder, however, the logic does not account for the possible transfer of NFTs. As such a user could claim the fees for their NFTs, then transfer all the NFTs to another address and claim with address. They could continually transfer the NFTs to new addresses and continue claiming fees until all fees are drained from the contract.

Open the report
CriticalUsers Can Claim The Most Expensive Reward Token UYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

In the function `_distributeFees()`, the input `_amount` of the token corresponding to the input `_tokenAddress` should be distributed amongst the NFT holders. However, fees are only tracked per `tokenId` and do not also track the corresponding token. This allows for users to claim the most expensive reward token, even if their fees were from a less expensive token.

Open the report
High`updateUserCakeBalance()` Uses Wrong Value When UYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

In the function `updateUserCakeBalance()` it has the following logic: ```solidity ownerUserElement.cakeTokenBalance += sPerfFeeCake; ``` Which increases the owners `cakeTokenBalance` by the sponsors performance fee. However, it should be increased by `perfFeeCake`, which is the performance fee for the owner. If the sponsors performance fee is more than half of the performance fee, then this can cause the contract to not have enough cake tokens for the balances of all accounts, which will cause some users to lose some of the cake tokens they are entitled to. If the sponsors performance fee is less than half of the performance fee, then there will be excess cake tokens that will be locked in the contract.

Open the report
HighIssues With Unclaimed Fees If NFT Is ChangedYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

If there are fees that have not been claimed and then `changeNFT()` is called to change to a new `nft` contract, then any unclaimed fees will be lost and can then be claimed by holders of the new `nft`.

Open the report
HighPotential Sandwich AttackYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

In the function `swap()` it takes an input `slippagePercent`. It then uses the `uniswapQuoter` to determine the expected amount out and calculates the `amountOutMinimum` using the input `slippagePercent`. The `uniswapQuoter` does this by determining the value of the swap in that transaction. As there is not actions that would affect the pool between the quote and the swap, this will mean that the swap will always yield the `amountOutQuote` provided by the `uniswapQuoter`. Thus it will always pass the slippage check. If users utilize this function to make swaps, then their swaps will be vulnerable to sandwich attacks. The function `moveRange()` uses the `swap()` function so that the protocols fees are also potentially vulnerable to this sandwich attack. However, the input `amount0Min` and `amount1Min` can help mitigate against this as these values are used to check the slippage when the new liquidity position is minted. As such, if these values are carefully calculated, they can revert a transaction if there is a significant amount of slippage. In addition, when increasing or decreasing liquidity, there is a risk of sandwich attack. However, there are minimum values in these cases to protect against slippage, which should be carefully chosen.

Open the report
MediumIncorrect InitializationYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The sited lines set initialize values to their initial state, in particular they should be set to the input values which use a trailing underscore as opposed to leading underscore. Many of these are immutable, so they can not be changed after deployment and thus would require redeploying a new contract with the corrected code.

Open the report
MediumIssue If `positionManager` Is ChangedYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

If the `positionManager` is changed, it may have a new factory and thus a new pool. However, `uniswapV3Pool` is not updated in the function `changePositionParameter`. Moreover, if the initial position NFT is minted, then changing the position manager will cause any functionality interacting with the liquidity to revert.

Open the report
MediumIssue If `RangePositionManager` Was Supported AndYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

If a user provides liquidity to a `rangePositionManager` and afterwards `updateRangePositionManagers()` is called before the user removes their liquidity and the `rangePositionManager` is not included and no longer supported, then the user will be unable to remove their liquidity from the `rangePositionManager`. Similarly if the user has uncollected fees, they will not be able to collect them.

Open the report
MediumIssues If `masterChef` Is Updated After Initial PYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

If the `masterChef` contract is changed after the initial position NFT is minted, then it will cause any function calls that interact with the liquidity to revert.

Open the report
Show 10 more
MediumLack of V3 Pool Validation May Lead To RevertYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

There is no validation that the `uniswapV3Pool` exists under the current `fee`. The contract may get `address(0)` and cause any operation that calls the pool to revert.

Open the report
MediumOwner Could Remove Users TokensYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

There are not checks that the input `_token` is `_WETH` if the `isETHNative` bool is true. This allows for the owner to withdraw tokens that are accounted for. Furthermore, note that this function may not be able to recover `WETH` from the contract, because if `withdrawExcessTokens(WETH, owner, false)` is called, then `contractBalance` will be the contracts balance of `WETH`. However, `accountedBalance` will be the accounted balance of native ETH, so that the `excessBalance` may not be correct.

Open the report
MediumOwner Liquidity Only Added On First Call To `mintYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The function `mintOwner()` is only designed to be called once to mint the initial position nft. However, this is enforced by checking that `totalLiquidity` is zero. If it is called and then all liquidity is removed later, then it may be called again. In this case `mintOwner` can successfully be called again, but the owner will still be in `isUser` array, so they will not have their `userElement.liquidity` updated. This will cause them to be unable to access the liquidity they added.

Open the report
MediumPotential To Run Out Of Gas And Cause Denial Of SYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

If the amount of users is high enough, then this can cause the function to exceed the block gas limit. A user with a large amount of NFTs could distribute them amongst many accounts to increase the list to execute a denial of service attack. We recommend allowing this logic to be executed over multiple transactions or setting an upper limit on the amount of users to ensure that this will not run out of gas. Currently the max amount of users as 10000, however, this is not a low enough maximum. During our testing using a mocked `yieldManager` (so the gas estimate here is likely lower than the actual value) an iteration of the for-loop in collect cost at minimum `16810` and at maximum `19305`. Iterating this 10000 times this equates to a minimum of 168,100,000 which exceeds the 30 million block gas limit.

Open the report
MediumTransfer Of NFT Can Be Used To Deny ServiceYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The function `increaseLiquidity()` makes the following check: ```solidity require(showEligible(userToIncrease), "Not eligible to enter the product"); ``` Which checks if the `NFT` balance of the `userToIncrease` is greater than or equal to the `productLock`. As such the design intent is to only allow users to participate when they hold a certain amount of NFTs. However, users can transfer their NFTs allowing other users to also participate in the protocol using the same NFT. A malicious could use `10000` different accounts and add liquidity with all of them. As there is a max amount of `10000` users, this would prevent any other users from entering the protocol.

Open the report
MediumUser Never Removed From ListYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

If a user withdraws all their liquidity, they are still included in the list of users. This contributes to the list growing large enough to hit the maximum or so that function calls will revert due to them exceeding the block limit.

Open the report
Low`approve` return value not checkedYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

Not all `IERC20` implementations `revert` when there's a failure in `approve`. The function signature has a `boolean` return value and they indicate errors that way instead. By not checking the return value, operations that should have been marked as failed may potentially go through without actually approving anything. Considering the `WETH` contract address can be changed, it may be changed to an address that does not revert on failure.

Open the report
Low`for` Loop OptimizationsYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The following operations can be made in all for loops of the codebase: 1. The increment operation saves a small amount of gas if performed from the left (`++i`) instead of from the righthand side (`i++`). 2. The increment operation can be placed in an `unchecked` block at the end of the loop logic, since it is bounded above by the loop limit which must be a `uint256` value, avoiding overflow.

Open the report
Low`getSqrtRatioAtTick()` Does Not Check That `absTiYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The function `getSqrtRatioAtTick()` does not check that the `absTick` is less than or equal to the `MAX_TICK`. As such this may return a value that is not between `MIN_SQRT_RATIO` and `MAX_SQRT_RATIO`.

Open the report
Low`safeApprove()` Is DeprecatedYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The function `safeApprove()` is deprecated and in some cases the entire approval may not be used, so that there will be a nonzero approval left for the contract.

Open the report
Show 10 more
LowAmbiguous EventYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

Recovering `WETH` using `recoverERC20()` would emit `Recovered(WETH, amount, to)`, however recovering `ETH` using `recoverETH()` would also emit `Recovered(WETH, amount, to)`.

Open the report
LowAvoid emitting events within loopsYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

Emitting an event costs at least 375 base gas plus 375 gas for each indexed parameter. Instead of emitting one event for each iteration of a loop, emit one event after the loop containing all of the relevant information instead. See [***HERE***](https://www.rareskills.io/post/ethereum-events#:~:text=Gas%20cost%20to%20emit%20Solidity%20event&text=Each%20event%20costs%20at%20least,words%20written%20to%20the%20chain.) for more information about the gas cost of events.

Open the report
LowCan Use Input To Save Storage ReadYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

In the lines sited above, the event is emitted using a storage variable. However, the storage variable is set to the input value prior to emitting the event. As such, the input can be used in the emitted event to save reading from storage.

Open the report
LowCan Use Single Division OperationYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

In the lines above it divides by 100 and then divides this result by 100. Instead a single division operation by 10000 can be done instead.

Open the report
LowConsider Using Custom ErrorsYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

Throughout the codebase, `require` statements returning sting error messages are used. From Solidity `v0.8.4`, there are more gas-efficient ways to explain to users why an operation failed than through strings. Using custom errors can significantly reduce the size of the deployed bytecode and reduce the gas cost when calls revert.

Open the report
LowDiscussion On `RewardNFT`YieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

Users NFTs are marked as in use up to the `_requiredAmount` according to their index as opposed to their `nftId`. This can cause issues if there will be NFTs that are worth more than others. In particular, if a user has a high value NFT, they may wish to not have it be marked as in use as opposed to a low value NFT. If the high value NFT was the first one they purchased, then it will be at index zero and always be marked as in use provided there is a nonzero `_requiredAmount`. A user must then transfer the high value token in order to have it be reindexed to a higher index so that it would not be marked in use.

Open the report
LowDiscussion On Sending/Refunding Of Tokens In `RanYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The function `collect()` in the `RangeMaster` contract calls `userCollect()` in the `rangePositionManager` for the `msg.sender`. The `rangePositionManager` contract will then send those tokens directly to the `msg.sender` if they are not the owner. If they are the `owner` then the appropriate amount is sent to the `feeReceiver` and the rest is sent to the `feeDistributor` to be distributed. As such, no tokens are sent to the `RangeMaster` contract, however, there is logic to then send the contracts balance of tokens to the `msg.sender`. Similarly, the function `decreaseLiquidity()` calls `rangePositionAddress.decreaseLiquidityUser()` which will refund directly to the `msg.sender`. For the function `increaseLiquidity()`, excess ETHER may have been sent as it is payable so there may be ether to refund. However, `rangePositionAddress.increaseLiquidityUser` refunds to the input `userToIncrease`, which is the `msg.sender.

Open the report
LowDiscussion On WeightYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

Can you please clarify the design intent behind `weights`. In particular, the weights are checked to sum up to `FACTOR` and then used in `increaseLiquidity()` to determine the percentage of the `weightAmount` of `weightToken` that should be set as the desired amount for each pool. One possible intent behind this is to ensure that when a user adds liquidity it is spread the liquidity in the given percentages (according to the `weightToken`) across all the supported pools. However, if this is the case, then it can be circumvented as the logic: ```solidity if (amountDesired0[i] == 0 && amountDesired1[i] == 0) { continue; } ``` Allows users to not add liquidity to a position. In particular, a user could have `amountDesired0[i] == 0 && amountDesired1[i] == 0` for all positions except one, and then choose the `weightAmount` so that the add the exact amount of liquidity they want to a single position. Furthermore, if a position is skipped the `weightAmount` must still account for the skipped position.

Open the report
LowDuplicate VariableYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

In the function `getPendingFees()`, there are two variables set for `rangePositionManagers.length`. ```solidity uint256 len = rangePositionManagers.length; uint rangeLength = rangePositionManagers.length; ```

Open the report
LowEvents Do Not Emit Previous StateYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

In the events cited above, that are emitted when state variables are changed, do not emit the previous value.

Open the report
Show 10 more
LowFeeDistributor Not Compatible With All ERC721 TokYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The `FeeDistributor` makes the following call `nft.totalSupply()` so that it cannot support all ERC721 tokens. This is because the ERC721 standard does not require the implementation of a `totalSupply()` function. However, it will support tokens that follow the enumeration extension (see [here](https://eips.ethereum.org/EIPS/eip-721#:~:text=The%20enumeration%20extension%20is%20OPTIONAL%20for%20ERC%2D721%20smart%20contracts%20(see%20%E2%80%9Ccaveats%E2%80%9D%2C%20below).%20This%20allows%20your%20contract%20to%20publish%20its%20full%20list%20of%20NFTs%20and%20make%20them%20discoverable.))

Open the report
LowFunction Can Be Modified With `pure` Or `view`YieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The function `onERC721Received()` does not require modifying the contract state, nor does it receive Ether. However, this function is not labeled with the `pure` or `view` modifier.

Open the report
LowIncompatibility with Fee On Transfer TokensYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

When transferring fee on transfer 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 Throughout the codebase bookkeeping is performed assuming that the amount transferred will be the same as the amount received.

Open the report
LowIncorrect Zero Address ValidationYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

In the `constructor()` there is the following check: ```solidity require(_token0 != address(0) || _token1 != address(0), "token cant be 0 address"); ``` Which will pass if one of the input `_token0` or `_token1` is not the zero address. However, it will not revert if `_token0` is the zero address while `_token1` is a nonzero address or if `_token0` is a nonzero address and `token1` is the zero address.

Open the report
LowInefficient Memory ParameterYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

One or more parameters with `memory` data location are never modified in their functions and those functions are never called internally within the contract. Thus, their data location can be changed to `calldata` to avoid the gas consumption copying from calldata to memory. `setBaseURI` has memory location parameters: `baseURI`.

Open the report
LowInefficient SwapYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The contract will swap to all of one token type and then use the `amountToSwap` to swap it back. Thus one may pay a swap fee on tokens unnecessarily.

Open the report
LowLack Of Indexed Event ParametersYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

Throughout the codebase events do not index their parameters.

Open the report
LowMissing Emit EventYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

Functions that update state variables should emit relevant events as notifications.

Open the report
LowMissing Input ValidationYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

### FeeDistributor - In the function `claimFees()`, the input `_tokenAddress` is not checked to be a registered token. - In the function `getTotalAndFeesPerNFT()`, the input `_tokenAddress` is not checked to be a registered token. - In the function `getClaimableFees()`, the input `_tokenAddress` is not checked to be a registered token. ### RangeMaster - In the `constructor()`, the input `_rangeWeights[i]` are not checked to be nonzero for all `i`. - In the function `updateRangePositionManagers()`, the input `_rangeWeights[i]` are not checked to be nonzero for all `i`. ### RangePositionManager - In the `constructor()`, the input `_distributionFee()` is not checked to be less than `10000`. We recommend determining the maximum distribution fee that would ever be charge and checking the input is less than this value. - In the function `moveRange()`, the input `amountToSwap` is not checked to be nonzero. Alternatively, logic can be added to handle when the amount is zero. - In the function `mintOwner()`, if `token0` or `token1` is WETH, it is not checked that the `msg.value` is equal to `amountDesired0` or `amountDesired1` respectively. ### SwapManager - In the function `swap()`, it is missing a check that if the `msg.value` is nonzero that it is equal to the input `amountIn ### RewardNFT - The function `batchMint()` does not check that the input amount is nonzero. This allows the function to be called successfully, when no tokens are minted.

Open the report
LowMissing Zero Address ValidationYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

### FeeDistributor - `constructor()` is missing a check that the input `_nftAddress` is not `address(0)`. - `receiveERC20Fees()` is missing a check that the input `_tokenAddress` is not `address(0)` as the contract is designed to distribute Ether through the `receive()` function. ### RangeMaster - `constructor()` is missing a check that the input `_rangePositionManagers[i]` is not `address(0)` for each `i`. - `updateRangePositionManagers()` is missing a check that the input `_rangePositionManagers[i]` is not `address(0)` for each `i`. ### RangePositionManager - `constructor()` is missing a check that the input `_positionManager` is not `address(0)`. - `constructor()` is missing a check that the input `_swapManager` is not `address(0)`. - `increaseLiquidityAuto()` is missing a check that the input `userToIncrease` is not `address(0)`. - `setMoveRangeAddress()` is missing a check that the input `moveAddress` is not `address(0)`. - `setMasterChef()` is missing a check that the input `newMasterChef` is not `address(0)`. - `setFeeDistributorSwapper()` is missing a check that the inputs `newFeeDistributor` and `newSwapManager` are not `address(0)`.

Open the report
Show 10 more
LowNo Error MessageYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The check `require(liquidity <= userElement.liquidity);` does not provide a string error message, which can cause difficulties determining why an operation reverted.

Open the report
LowNon-External Functions And Variables Do Not FolloYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The sited variables and functions do not conform to the solidity style guide (see [here](https://docs.soliditylang.org/en/latest/style-guide.html#underscore-prefix-for-non-external-functions-and-variables)). The style guide recommends that all non-external variable and function names have an underscore prefix.

Open the report
LowOrder Of Functions Does Not Follow Style GuideYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The contracts/library sited above do not follow the solidity style guide (see [here](https://docs.soliditylang.org/en/latest/style-guide.html#order-of-functions)) for the order of functions. According to the style guide, the order of functions should be: - constructor - receive function (if exists) - fallback function (if exists) - external - public - internal - private Within a grouping, place the view and pure functions last.

Open the report
LowOrder Of Layout Does Not Follow Style GuideYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The order of layout of the contracts sited above do not follow the solidity style guide (see [here](https://docs.soliditylang.org/en/latest/style-guide.html#order-of-layout)). According to the style guide inside each contract the following order should be used: - Type declarations - State variables - Events - Errors - Modifiers - Functions

Open the report
LowPosition Managers Should Never Change Their `_reqYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

If the `_requiredAmount` is changed to be a larger value for a `rangePositionManager` and a user had already had their NFTs marked as in use, then the NFTs that were already marked as in use will have their `countNFTUsing` incremented again and be pushed a second time to the `userRangePositionManagerNFTs` array unnecessarily. Currently the `_requiredAmount` is given by the immutable `_productLock` in `RangePositionManager`, so that it will not be changed.

Open the report
LowPotential Locked Tokens And EtherYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The function `distributeFees()` distributes an `_amount` of ETH or ERC20 token that was received using the following logic: ```solidity feeInfo[_tokenAddress].feesPerNFT += _amount / totalNFTs; feeInfo[_tokenAddress].totalFees += _amount; ``` However, the `feesPerNFT` is rounded down so that `feesPerNFT * totalNFTs` may be less than the provided `_amount`. The tokens are distributed according to the `feesPerNFT`, so the difference will not be distributed and locked in the contract. --- Similarly the function `collect()` distributes an `amount0` and `amount1` of ETH or ERC20 token using the following logic: ```solidity uint share0 = amount0 * userElement.liquidity / totalLiquidity; uint share1 = amount1 * userElement.liquidity / totalLiquidity; ``` However, these share values are rounded down so that they may add up to less than the collected amount. The difference will be locked in the contract. Moreover, depending on the frequency of this call and the token decimals users with a small amount of liquidity may receive 0 shares of the collected fees. It should be carefully checked that there is enough precision so that during the normal operations of the protocol users with a small amount of liquidity still receive their fair share of the fees. Similarly for the performance fees, which are taken from the calculated shares.

Open the report
LowPotential ReentrancyYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

Reentrancy can occur when the contract creates a function that makes an external call to another untrusted contract before resolving any effects. If an attacker can control the untrusted contract, they can make a recursive call back to the contract, repeating interactions that would have otherwise not run after the external call resolved the effects. If a token using hooks is used, then when the token is transferred the hook may be used to reenter the contract. Note that this is given an *informational* severity as in the current codebase this only emits events out of order.

Open the report
LowPotential Swept Or Unwrapped Tokens Not AccountedYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

In the function `collect()`, it makes the following calls: ```solidity positionManager.unwrapWETH9(0, address(this)); IWETH9(WETH).withdraw(IERC20(WETH).balanceOf(address(this))); positionManager.sweepToken(token0, 0, address(this)); positionManager.sweepToken(token1, 0, address(this)); ``` These will sweep any WETH, token0, or token1 tokens in the `positionManager` contract, and will convert any WETH held by the contract to ETH. However, only the output `amount0` and `amount1` from the `positionManager.collect()` are handled in the logic. If there are any tokens accidentally sent to the `positionManager` then more tokens may be received and locked in the contract.

Open the report
LowProtocol Only Supports Native ETH And Does Not SuYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The contracts assume that if `WETH` is used as an input, that the user will be supplying native ETH and not WETH. As such the protocol does not support users utilizing WETH.

Open the report
LowRangePositionManager Can Receive Any ERC721YieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

`RangePositionManger` includes an `onERC721Received()` function so that it can receive ERC721 tokens using the `safeTransferFrom()` functionality. However, this allows it to accept any ERC721 tokens, when it is only designed to handle those from the `positionManager`. If another ERC721 token is accidentally sent to the contract it will be locked in the contract.

Open the report
Show 10 more
LowRedundant And Unused Struct ElementsYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

In the struct `RangePosition`, the elements `added` and `updated` are redundant as they are both updated to be `block.timestamp`. In the struct `RangePosition`, the element `locked` is only ever set to `false` and is not used in the logic of the contract.

Open the report
LowSpecific Imports Are Not UsedYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

Specific imports are recommended to be used to avoid unpredictable pollution of the namespace. For example: import {A, B, C} from "X";

Open the report
LowSwap Using a Single Fee May Be SuboptimalYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

Uniswapv3swapper uses hardcoded `fee` to make a swap. This can result in a swap being conducted in a pool with little liquidity and with a high price impact.

Open the report
LowTypos and InconsistenciesYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

### RangeMaster - The error message in the `constructor()` for the `yieldManager` references the `owner` as opposed to the `yieldManager`. - The inputs `amountDesired0` and `amountDesired1` in the function `decreaseLiquidity()` do not reflect that they are minimum values. ### SwapManager - The comments for the `constructor()` only states "0 representing Uniswap" and does not state that 1 represents PancakeSwap. - The comment "// Perform the token swap using Uniswap V3 SwapRouter (example code, comment only" does not seem to apply. ### RangePositionManager - The `moveRangeAddresses` mapping also gives access to call `increaseLiquidityAuto`. We recommend changing the name to reflect this additional privilege.

Open the report
LowUnnecessary `onERC721Received()` FunctionYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The `onERC721Received()` function is only called during safe operations, which first checks if it is being sent to a contract. If it is a contract, then it attempts to call `onERC721Received()` of that contract and will revert if this does not return the `onERC721Received.selector`. As such, the ability to receive NFTs through the use of safe operations can be removed by not including the `onERC721Received()` function as opposed to directly disabling it. Note, that NFTs can still be transferred to the contract if the safe operations are not used.

Open the report
LowUnnecessary ApprovalYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

In the WETH contract at address [0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2](https://etherscan.io/token/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code), the function `withdraw()` uses the balance of the `msg.sender` and does not use any approval. If the WETH contracts that are to be used will always follow this convention, then the approval can be removed.

Open the report
LowUnnecessary CastingYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

In the function `setMasterChef()`, `newMasterChef` is cast as an `address`, however, it is already of type `address`.

Open the report
LowUnnecessary Condition In `_onlyOwner()`YieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The function `_onlyOwner()` in the contract `FeeDistributor`, `RangeMaster`, `RangePositionManager`, and `SwapManager` requires that either the `msg.sender` is the `owner` or `address(this)`. However, the `onlyOwner` modifier is used on functions that are never called by the contract itself. As such the `msg.sender` will never be `address(this)`.

Open the report
LowUnused EventYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

The event `NewMaxUsers` is never emitted.

Open the report
LowUse `uint256` Instead of `uint`YieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

Throughout the codebase `uint` and `uint256` are used interchangeably.

Open the report
Show 1 more
LowWrong Parameter Emitted In EventYieldFlow - Audit 2 · CertiK · 12 Apr 2024Fixed

In the function `acceptFeeReceiver()` it emits the event ```solidity emit NewFeeReceiver(owner); ``` However, the input should be the new `feeReceiver` not the `owner`.

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="yieldflow"
></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