As of 14 Oct 2026, Froggies has 1 audit report on Trustblock, by CertiK, dated 4 Aug 2023. That report lists no open critical findings.
Record last updated . It holds audits and findings, contracts and incidents up to Oct 2026. Statuses are the security firms’ own. Trustblock does not review code.
Newest first
| Audit | Security firm | Date | Scope | Critical findings | Report |
|---|---|---|---|---|---|
| Froggies Token | Security firm: CertiK | Date: | Scope: Files named in the report | 1 critical finding, fixed | Open · skynet.certik.com |
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 1 |
| High | 3 | 0 | 2 |
| Medium | 0 | 0 | 1 |
| Low | 7 | 0 | 5 |
In the contract `StakingContract` 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. - Function `setPeriodRates()`: Sets the reward rate for the specified `period`. - Function `addToStakingPool()`: Provides tokens for distributing rewards. - Function `setEmergencyWithdrawalRates()`: Set the following state variables - `emergencyWithdrawalPenalty`: Records the rate of penalty when a user uses emergency withdrawal. - `burnRateEmergency`: Records the percentage of tokens which will be burned from penalty. - `poolRateEmergency`: Never used state variable. 
Open the reportIn the contract `Token` the role `_owner` has authority over the functions shown in the diagram below. - `setPair()` and `_setPair()`: Manage the usage status of pairs in this contract. The owner can add new pairs, or disable an active pair. - `setBuyTaxes()`: Set the fee rate when users get the `LLFR2` token from a pair. - `setSellTaxes()`: Set the fee rate when users use the `LLFR2` token to get other tokens from a pair. - `setLPThreshold()`: Set the value of the state variable `lpThreshold`. Transactions with the pair will accumulate `lp` fee, once the `lp` fee meets the `lpThreshold`, the contract will use all of the `lp` fees to add liquidity to the `LLFR2-WBNB` pair - `setMarketingThreshold()`: Set the value of the state variable `marketingThreshold`. - `setMarketingSwap()`: Set the value of the state variable `isSwap`. When the `isSwap` is true, the contract will swap all of the market fees to BNB. - `excludeFromFees()`: Manage the addresses that don't need to pay transaction fees. - `withdrawBNB()`: Withdraw the BNBs swapped from the market fees. - `withdrawMarketingTokens()`: Withdraw the `LLFR2`s that earned from the market fees. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority. 
Open the reportIn the contract `Token`, the EOA address `owner` has `100000000000000 * 10 ** decimals()` tokens minted at the time of the contract deployment, which has severe centralization risk and can manipulate the tokenomics of the project. ```solditiy=53 constructor(address _router) ERC20("LLFR2", "LLFR2") { _mint(msg.sender, 100000000000000 * 10 ** decimals()); ``` Also, the contract will use a part of the transaction fee to add liquidity, but the LP tokens are transferred to the EOA address `owner`, this contract logic results in a centralized token holding position over time. ```solidity=94 function addLiquidity(uint256 tokenAmount, uint256 bnbAmount) private { _approve(address(this), address(uniswapV2Router), tokenAmount); uniswapV2Router.addLiquidityETH{value: bnbAmount}( address(this), tokenAmount, 0, 0, owner(), block.timestamp ); } ``` Any compromise to the private keys of the `owner` EOA address may allow a hacker to take advantage of the EOA address authority and sell tokens on the market and/or remove the pool liquidity, causing a severe price drop.
Open the reportPerforming integer division before multiplication truncates the low bits, losing the precision of calculation. ```solidity=77 uint256 totalAllocation = _amount.mul(totalRate).div(100); ``` ```solidity=83 uint256 burnAmount = totalAllocation.mul(_burnRate).div(100); ``` --- ```solidity=104 uint256 rewardPerSecond = stakers[_staker].totalRewardAllocation.div(stakers[_staker].stakePeriod); ``` ```solidity=105 uint256 newReward = rewardPerSecond.mul(timeElapsed); ``` --- ```solidity=156 uint256 penalty = total.mul(emergencyWithdrawalPenalty).div(100); ``` ```solidity=157 uint256 burnAmount = penalty.mul(burnRateEmergency).div(100); ``` --- ```solidity=209 uint256 rewardPerSecond = stakers[_staker].totalRewardAllocation.div(stakers[_staker].stakePeriod); ``` ```solidity=210 uint256 accumulatedReward = rewardPerSecond.mul(timeElapsed); ```
Open the reportThe field `stakeTime` in the struct `Staker` is not updated in the function `unstake()`. --- The field `stakePeriod` in the struct `Staker` is not updated in the functions `unstake()` and `emergencyUnstake()`. --- The reward amount has been mistakenly added 2 times to the state variable `totalAllocated`. The total reward amount `totalAllocation` a user can receive is added to the state variable `totalAllocated` in the `stake()` function. ```solidity=95 totalAllocated = totalAllocated.add(totalAllocation); ``` Furthermore, in the `calculateReward()` function, the newly generated rewards are added to the state variable `totalAllocated`. This portion of the rewards is already included in the total rewards, so the code at line 110 duplicates the addition. ```solidity=110 totalAllocated = totalAllocated.add(newReward); ``` In addition, the state variable `totalAllocated` is also updated in the functions `unstake()` and `emergencyUnstake()`. ```solidity=138 totalAllocated = totalAllocated.sub(reward); ``` ```solidity=175 totalAllocated = totalAllocated.sub(uncollectedReward).add(poolAmount); ``` --- The amount of burned tokens has been mistakenly added 3 times to the state variable `totalBurned`. The amount of tokens that will be burned is added to the state variable `totalBurned` in the `stake()` function. ```solidity=96 totalBurned = totalBurned.add(burnAmount); ``` And this amount is also added to the state variable `totalBurned` in the `unstake()` function before executing the `burn` function. ```solidity=139 totalBurned = totalBurned.add(burnAmount); burn(burnAmount); ``` Finally, when the function `burn()` executes, this amount is added to the state variable `totalBurned` again. ```solidity=203 totalBurned = totalBurned.add(amount); ```
Open the reportBased on our understanding, when the period has not ended, and a user wants to withdraw their staked tokens, they need to call the `emergencyUnstake()` function and accept the associated penalty. Therefore, it is necessary to validate the current time to prevent users from mistakenly calling the function and incurring financial losses.
Open the reportThe smart contract contains low-level calls such as `.call()`, `.delegatecall()`, and `.staticcall()`. Since these calls bypass some of the automatic checks that Solidity provides, like function type checks, they can introduce vulnerabilities, logic errors, or unexpected behavior. ```solidity=201 (bool success, ) = address(token).call(abi.encodeWithSignature("publicBurn(uint256)", amount)); ```
Open the reportThere should always be events emitted in the sensitive functions that are controlled by centralization roles.
Open the reportA sandwich attack may 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 (executing before the target) a transaction to purchase one of the assets and make profits by back running (executing after the target) a transaction to sell the asset. The following functions are called without setting restrictions on slippage or minimum output amount. Hence, transactions triggering these functions are vulnerable to sandwich attacks, especially when the input amount is large : - `addLiquidity()` - `_swapTokensForBNB()` - `_swapTokensForBNBSimple()`
Open the reportThe 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 reportThe reports name a repository or files. Open a report to see its scope.
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.
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.
<head><script src="https://widget.trustblock.run/project-widget.min.js" defer></script></head><body><divdata-tb-project-widgetdata-tb-project-slug="froggies-token"></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