WanPlan

CertiKFiles named in the report

CertiK reviewed WanPlan on 9 Nov 2022: 23 findings, 1 critical; 14 marked fixed, 1 acknowledged, 8 open.

1 critical finding, fixed
Open the reportOpen WanPlan’s security record

Report hosted on skynet.certik.com.

Trustblock does not review code.

Findings23

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

SeverityOpenAcknowledgedFixed
Critical001
High010
Medium000
Low8013
CriticalUnsafe Argument `_num` In Function `stake()` andFixed

Inputting negative numbers into the functions `stake()` and `unstake()` can cause unexpected behaviors. --- In the function `stake()`, the argument `_num` is of type `int256`. This allows a user to input a negative number, meaning they intend to stake a negative amount of tokens. ```solidity=112 function stake(int _num, address _to) public { ``` During the transfer of tokens from the user to the contract, argument `_num` is casted to type `uint256`. The result will be a large positive number. This may cause an unintended amount of `lpToken` to be transferred into the contract by the user. ```solidity=127 lpToken.transferFrom(msg.sender, address(this), uint(_num)); ``` The mapping `stakeNum` keeps track of a user's staked amount. Although `uint(_num)` amounts of tokens were transferred, the mapping will incorrectly decrease in value by the value `_num`. ```solidity=128 stakeNum[_to] += _num; stakeTotal += _num; ``` --- In the function `unStake()`, the argument `_num` is of type `int256`. This allows a user to input a negative number, meaning they intend to unstake a negative amount of tokens. ```solidity=134 function unStake(int _num) public { ``` If `_num` is a negative number, the `require` check that ensures the user has a greater or equal balance of staked tokens than the amount to unstake, can be bypassed. ```solidity=135 require(stakeNum[msg.sender] >= _num, "Error:stake lpToken balance not enough"); ``` The value `_num` is casted to type `uint256`, resulting in a large positive number. `uint(_num)` amount of tokens will then be incorrectly transferred out of the contract and to the user. The user is able to unstake `uint(_num)` amount of tokens without initially staking that same amount. ```solidity=148 lpToken.transfer(msg.sender, uint(_num)); ``` The mapping `stakeNum` will incorrectly increase in value by the value `_num`. ```solidity=149 stakeNum[msg.sender] -= _num; stakeTotal -= _num; ```

LowCostly Operation Inside LoopFixed

Accessing storage variables in a loop can be costly in terms of gas consumption. The storage variables `LinerReleaseRemain` and `LinerReleaseCount` are likely to be read and updated multiple times during the `for` loop. ```solidity=658 for (; LinerReleaseRemain > 0; LinerReleaseCount++) { if (ConstructTime + (LinerReleaseCount + 1) * 864000 >= block.timestamp) { return; } if (LinerReleaseRemain / (4000 * 1 ether) > 0) { balances[techCommunityAddress] += (4000 * 1 ether); LinerReleaseRemain -= (4000 * 1 ether); } else { balances[techCommunityAddress] += LinerReleaseRemain; LinerReleaseRemain = 0; } } ```

LowFunction `approve` of Contract `WantImplementatioFixed

It is expected behavior that calls of the form `approve(spender, amount)` fail if the address in `spender` is the zero address.

LowFunction `transferFrom` of Contract `WantImplemenFixed

It is expected behavior that calls of the form `transferFrom(from, dest, amount)` fail if the `from` address is zero.

LowFunction Should Be Declared ExternalFixed

Functions which are never called internally within the contract should have `external` visibility.

LowLocked EtherFixed

The contract has one or more payable functions, but does not have a function to withdraw the funds. ```solidity=384 function buy(uint256 _count) public payable { ```

LowMissing Zero Address ValidationFixed

Addresses should be checked before assignment or external calls to ensure they are not `address(0)`.

LowMisspelled Variable NameFixed

The variable names `LinerReleaseCount` and `LinerReleaseRemain` are misspelled throughout the contract.

LowPotential Dangerous InequalityFixed

The reserve amounts of `WantAddr` and `TradeCoinAddr` tokens are retrieved from the external call to the `pair` address: ```solidity=410 (uint reserveA, uint reserveB,) = pair.getReserves(); ``` The inequality of the addresses `WantAddr` and `TradeCoinAddr` is then checked in order to determine which address corresponds to which reserve value, either `reserveA` or `reserveB`. ```solidity=412 if (WantAddr < TradeCoinAddr) { ``` However, the inequality is not a guaranteed method of matching the addresses to the corresponding reserve values because the implementation of the external contract `pair` could have a different mechanism of ordering the two addresses. The call to `pair.getReserves()` could return a different ordering of reserve values.

LowTokens Are Never Sent To Burn Address During `traFixed

A fee is taken on token transfers during the call to `transferFrom()`. However, the `burn` portion of the fee is missing as tokens are never transferred to the zero address. The event of transferring tokens to the zero address is still emitted. ```solidity=436 if (_tax != 0) { balances[stakeLPAddress] += (_tax * lpTax / 10000); balances[valueInstituteAddress] += (_tax * valueInstituteTax / 10000); emit Transfer(_from, stakeLPAddress, (_tax * lpTax / 10000)); emit Transfer(_from, valueInstituteAddress, (_tax * valueInstituteTax / 10000)); emit Transfer(_from, address(0), (_tax * burnTax / 10000)); // Burn event is emitted but never executed } ```

Show 4 more
LowUnnecessary Use of `SafeMath`Fixed

The `SafeMath` library is used unnecessarily. With Solidity compiler versions `0.8.0` or newer, arithmetic operations will automatically revert in case of integer overflow or underflow. --- ```solidity=105 using SafeMath for uint256; ``` - `SafeMath` library is used for `uint256` type in `WantImplementation` contract, in file `Want.sol` --- ```solidity=295 using SafeMath for uint256; ``` - `SafeMath` library is used for `uint256` type in `WantSale` contract.

LowUnsafe Integer CastFixed

The type casting from unsigned integer `uint` to the integer `int` and vice versa, may cause the values to become truncated or have the incorrect positive or negative sign. This can cause unexpected behaviors and errors if the bounds of type casting is not checked. ```solidity=101 heights.push(HeightProfit(0, int(block.number), _ratio, stakeTotal)); ``` - Type conversion `int256(block.number)` from type `uint256` to type `int256`. --- ```solidity=103 heights.push(HeightProfit(heights[heights.length - 1].height + 1, int(block.number), _ratio, stakeTotal)); ``` - Type conversion `int256(block.number)` from type `uint256` to type `int256`. --- ```solidity=113 require(int(lpToken.balanceOf(msg.sender)) >= _num, "Error: lp token balance not enough"); ``` - Type conversion `int256(lpToken.balanceOf(msg.sender))` from type `uint256` to type `int256`. --- ```solidity=121 lastClaimHeightMap[_to] = int(heights.length); ``` - Type conversion `int256(heights.length)` from type `uint256` to type `int256`. --- ```solidity=123 lastClaimHeightMap[_to] = int(heights.length) - 1; ``` - Type conversion `int256(heights.length)` from type `uint256` to type `int256`. --- ```solidity=127 lpToken.transferFrom(msg.sender, address(this), uint(_num)); ``` - Type conversion `uint256(_num)` from type `int256` to type `uint256`. --- ```solidity=141 lastClaimHeightMap[msg.sender] = int(heights.length); ``` - Type conversion `int256(heights.length)` from type `uint256` to type `int256`. --- ```solidity=143 lastClaimHeightMap[msg.sender] = int(heights.length) - 1; ``` - Type conversion `int256(heights.length)` from type `uint256` to type `int256`. --- ```solidity=148 lpToken.transfer(msg.sender, uint(_num)); ``` - Type conversion `uint256(_num)` from type `int256` to type `uint256`. --- ```solidity=159 lastClaimHeightMap[msg.sender] = int(heights.length); ``` - Type conversion `int256(heights.length)` from type `uint256` to type `int256`. --- ```solidity=161 lastClaimHeightMap[msg.sender] = int(heights.length) - 1; ``` - Type conversion `int256(heights.length)` from type `uint256` to type `int256`. --- ```solidity=191 for (int i = index + 1; i < int(heights.length); i++) { ``` - Type conversion `int256(heights.length)` from type `uint256` to type `int256`. --- ```solidity=192 sum += stakeNum[_owner] * heights[uint(i)].ratio; ``` - Type conversion `uint256(i)` from type `int256` to type `uint256`. --- ```solidity=199 for (int i = 0; i < int(heights.length); i++) { ``` - Type conversion `int256(heights.length)` from type `uint256` to type `int256`. --- ```solidity=200 sum += heights[uint(i)].total * heights[uint(i)].ratio; ``` - Type conversion `uint256(i)` from type `int256` to type `uint256`. --- ```solidity=421 stake.stake(int(_li), msg.sender); ``` - Type conversion `int256(_li)` from type `uint256` to type `int256`.

LowUnused Code ComponentsFixed

The following code components are never used in the contract `WantSale.sol`. ```solidity=297 address public GMAddr; ``` ```solidity=317 uint256 private PeriodStartSaleHeight; uint256 private PeriodEndSaleHeight; ``` ```solidity=320 bool public PublicBuy; ``` ```solidity=351 address public UniswapV2RouterAddr; ```

LowUnused Return VariableFixed

The local variables are returned instead of the return variable. ```solidity=109 return sum; ``` - The local variable `sum` is returned in place of the return variable `_reward`, which is never written. --- ```solidity=178 return sum; ``` - The local variable `sum` is returned in place of the return variable `_available`, which is never written. --- ```solidity=194 return sum; ``` - The local variable `sum` is returned in place of the return variable `_reward`, which is never written. --- ```solidity=202 return sum; ``` - The local variable `sum` is returned in place of the return variable `_reward`, which is never written.

Contracts in scope

No deployed address is recorded for this audit.

The report names a repository or files. Open the report to see its scope.

Repository and files the report names (3)

  • Deposit.sol
  • Want.sol
  • WantSale.sol

Part of WanPlan’s security record

WanPlan
Audits1 audit by 1 firmLast audit Nov 2022, by CertiK.
Critical findingsNo open critical findingsIn that report, 1 critical finding was reported. It is marked fixed by the firm that reported it.
Open WanPlan’s security record

Security firm

CertiK

1,044 projects reviewed · 1,375 reports · latest May 2025

See CertiK’s audits

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