Quantstamp reviewed Lendroid Whalestreet on 26 Nov 2020: 9 findings, 0 critical; 8 marked fixed, 1 acknowledged.
Report hosted on certificate.quantstamp.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 | 3 |
| Medium | 0 | 1 | 3 |
| Low | 0 | 0 | 2 |
If a user stakes at epoch `X`, and claims his reward at epoch `Y` using `BasePool.unstakeAndClaim` or `BasePool.claim`, and if `Y` is higher enough than `X`, transactions will most likely throw due to running out of gas or will hit the block gas limit. As a result, users will lose all their rewards. This issue is due to the use of a loop inside `BasePool.earned` function that iterates over all previous epochs from `lastEpochRewardsClaimed` until the current epoch relative to the block timestamp. Note that `lastEpochRewardsClaimed's` default value is zero; hence, late stakers will face the same issue, since the iteration necessarily starts from epoch zero.
Total rewards between epochs 85 and 336 is almost doubled of what it should be. According to the specification and documentation in the code, the total rewards between epochs 85 and 336 should be 21.6M, but it is currently set to 41,850,000: ``` // UNIV2SHRIMPPool.sol function totalRewardsInEpoch(uint256 epoch) … { . . . else if (epoch > 84 && epoch <= 336) { totalRewards = 41850000 * (10 ** 18);// 21.6 M } . . . } ```
The users staked amount at epoch X will not allow them any reward at epoch Y if X < Y , meaning that their staked LP tokens are not accumulated when computing the rewards for each epoch.
Following the `$HRIMP` distribution per epoch table as stated in the specification, the start time is set to be December 4th, 2020. However, in `BasePool.sol` (L30), `starttime` is set to `HEARTBEATSTARTTIME`, which in turn, is equal to the `1602288000` timestamp (`2020-10-10 00:00:00 (UTC UTC +00:00)`). Hence, the start time in the code is inconsistent with the spec.
In `totalRewardsInEpoch`, L88-92 adjusts `totalRewards` using a logic that is not currently documented and therefore could not be validated. As such, its effect is currently undetermined. As a consequence to this issue the total distributed reward in a series will be way less than the original `totalRewards` amounts since the number of epochs multiplied by the final reward value will be less than the original documented and set `totalRewards` values.
Epoch zero reward will never be distributed since `BasePool.stake` will be allowed to execute only after `starttime` where `starttime` is equal to `HEARTBEATSTARTTIME`. In the opposite `_currentEpoch` will return zero only if the block timestamp is lower than `HEARTBEATSTARTTIME`. At any given timestamp the stated condition will not be satisfied simultaneously, meaning that when staking will be allowed the current epoch will be epoch 1.
The address parameters received as input parameters do not have any sanity checks. Example: in the constructor of `LPTokenWrapper.sol`, the `lpTokenAddress` could be `0x0`. If so, the underlying `lpToken` will also be `0x0`, which will lead to all operations dependent on it to fail.
A user staking right before the end of an epoch will still be able to get the reward for the ongoing reward even if he staked for only one block.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (4)
236 projects reviewed · 332 reports · latest Oct 2026
See Quantstamp’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