CertiK reviewed IceCreamSwap on 6 Jul 2023: 6 findings, 0 critical; 3 marked fixed, 1 acknowledged, 2 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 | 0 | 0 | 0 |
| Medium | 0 | 1 | 3 |
| Low | 2 | 0 | 0 |
When transferring deflationary ERC20 tokens, the input amount is not be equivalent 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. A failure to account for such fees will allow the same user to withdraw 100 tokens from the contract, which causes the contract to lose 10 tokens in such a transaction. ```solidity=314 lpToken[_pid].safeTransferFrom(msg.sender, address(this), _amount); ``` - Transferring tokens by `_amount`. ```solidity=316 user.amount = user.amount.add(_amount); ``` - This function call executes the following operation. - In `SafeMath.add`, - `uint256 c = a + b;` - The `_amount` appears to be used for bookkeeping purposes without compensating the potential transfer fees.
A reentrancy attack can occur when the contract creates a function that makes an external call to another untrusted contract before resolving any effects. If the attacker can control the untrusted contract, they can make a recursive call back to the original function, repeating interactions that would have otherwise not run after the external call resolved the effects. ### External call(s) ```solidity=309 // FALSE POSITIVE settlePendingIce(msg.sender, _pid, multiplier); ``` * This function call executes the following external call(s). * In `SafeERC20._callOptionalReturn`, * `returndata = address(token).functionCall(data,"SafeERC20: low-level call failed")` * In `IceCreamFarm._safeTransfer`, * `ICE.safeTransferFrom(iceTreasury,_to,_amount)` * In `Address.functionCallWithValue`, * `(success,returndata) = target.call{value: value}(data)` ```solidity=314 // FALSE POSITIVE lpToken[_pid].safeTransferFrom(msg.sender, address(this), _amount); ``` ### State variables written after the call(s) ```solidity=325 poolInfo[_pid] = pool; ``` ```solidity=316 user.amount = user.amount.add(_amount); ``` ```solidity=322 user.rewardDebt = user.amount.mul(multiplier).div(BOOST_PRECISION).mul(pool.accIcePerShare).div( ACC_ICE_PRECISION ); ``` ### Cross-function reentrancy into these function(s) ```solidity=157 function poolLength() public view returns (uint256 pools) { ``` ```solidity=168 function add( ``` ```solidity=203 function set( ``` ```solidity=247 function massUpdatePools() public { ``` ```solidity=275 function updatePool(uint256 _pid) public returns (PoolInfo memory pool) { ``` ```solidity=491 function getBoostMultiplier(address _user, uint256 _pid) public view returns (uint256) { ``` ### External call(s) ```solidity=341 settlePendingIce(msg.sender, _pid, multiplier); ``` * This function call executes the following external call(s). * In `SafeERC20._callOptionalReturn`, * `returndata = address(token).functionCall(data,"SafeERC20: low-level call failed")` * In `IceCreamFarm._safeTransfer`, * `ICE.safeTransferFrom(iceTreasury,_to,_amount)` * In `Address.functionCallWithValue`, * `(success,returndata) = target.call{value: value}(data)` ### State variables written after the call(s) ```solidity=344 user.amount = user.amount.sub(_amount); ``` ### Cross-function reentrancy into these function(s) ```solidity=491 function getBoostMultiplier(address _user, uint256 _pid) public view returns (uint256) { ``` --- ### External call(s) ```solidity=341 settlePendingIce(msg.sender, _pid, multiplier); ``` * This function call executes the following external call(s). * In `SafeERC20._callOptionalReturn`, * `returndata = address(token).functionCall(data,"SafeERC20: low-level call failed")` * In `IceCreamFarm._safeTransfer`, * `ICE.safeTransferFrom(iceTreasury,_to,_amount)` * In `Address.functionCallWithValue`, * `(success,returndata) = target.call{value: value}(data)` ```solidity=345 lpToken[_pid].safeTransfer(msg.sender, _amount); ``` ### State variables written after the call(s) ```solidity=351 poolInfo[_pid].totalBoostedShare = poolInfo[_pid].totalBoostedShare.sub( _amount.mul(multiplier).div(BOOST_PRECISION) ); ``` ```solidity=348 user.rewardDebt = user.amount.mul(multiplier).div(BOOST_PRECISION).mul(pool.accIcePerShare).div( ACC_ICE_PRECISION ); ``` ### Cross-function reentrancy into these function(s) ```solidity=157 function poolLength() public view returns (uint256 pools) { ``` ```solidity=168 function add( ``` ```solidity=203 function set( ``` ```solidity=247 function massUpdatePools() public { ``` ```solidity=275 function updatePool(uint256 _pid) public returns (PoolInfo memory pool) { ``` ```solidity=491 function getBoostMultiplier(address _user, uint256 _pid) public view returns (uint256) { ``` ### External call(s) ```solidity=386 _safeTransfer(burnAdmin, pendingIceToBurn); ``` * This function call executes the following external call(s). * In `SafeERC20._callOptionalReturn`, * `returndata = address(token).functionCall(data,"SafeERC20: low-level call failed")` * In `IceCreamFarm._safeTransfer`, * `ICE.safeTransferFrom(iceTreasury,_to,_amount)` * In `Address.functionCallWithValue`, * `(success,returndata) = target.call{value: value}(data)` ### State variables written after the call(s) ```solidity=387 lastBurnedBlock = block.number; ``` --- ### External call(s) ```solidity=413 burnIce(false); ``` * This function call executes the following external call(s). * In `SafeERC20._callOptionalReturn`, * `returndata = address(token).functionCall(data,"SafeERC20: low-level call failed")` * In `IceCreamFarm._safeTransfer`, * `ICE.safeTransferFrom(iceTreasury,_to,_amount)` * In `Address.functionCallWithValue`,
In the `deployPool()` function of the SmartChefFactory contract, there is a logic flaw where the `_stakedToken` and `_rewardToken` can be identical. This means that a user could stake the same token that is also used as a reward. This will lead to a loss of funds for the contract as the accumulated rewards are calculated with respect to the `_stakedToken` balance.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (7)
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