CertiK reviewed Paragons (ParagonsDAO - Audit) on 20 Sep 2022: 8 findings, 0 critical; 7 marked fixed, 1 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 | 0 | 1 |
| Low | 1 | 0 | 6 |
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=142 IERC20(pdt).transferFrom(msg.sender, address(this), _amount); ``` ### State variables written after the call(s) ```solidity=163 stakeDetails[_to] = stakeDetail; ``` ```solidity=146 totalStaked += _amount; ``` ```solidity=144 _adjustMeanMultilpier(true, _amount); ``` * This function call executes the following assignment(s). * In `PDTStaking._adjustMeanMultilpier`, * `adjustedTime = block.timestamp` * In `PDTStaking._adjustMeanMultilpier`, * `adjustedTime = previousTimeStaked + ((timePassed * percent) / 1e18)` * In `PDTStaking._adjustMeanMultilpier`, * `adjustedTime = previousTimeStaked - ((timePassed * percent) / 1e18)` --- ### External call(s) ```solidity=188 IERC20(pdt).transfer(_to, _amount); ``` ### State variables written after the call(s) ```solidity=189 stakeDetails[msg.sender] = stakeDetail; ```
The functions which are never called internally within the contract should have external visibility for gas optimization. ```solidity=225 function multiplierIndex() public view returns (uint256 index_) { ``` --- ```solidity=231 function meanMultiplier() public view returns (uint256 multiplier_) { ``` --- ```solidity=238 function userStakeMultiplier(address _user) public view returns (uint256 multiplier_) { ```
Addresses should be checked before assignment or external call to make sure they are not zero addresses. ```solidity=109 pdt = _pdt; ``` - `_pdt` is not zero-checked before being used. --- ```solidity=110 rewardToken = _rewardToken; ``` - `_rewardToken` is not zero-checked before being used.
If enough time has passed since a user staked tokens, such that: `previousTimeStaked - ((percentStakeDecreased * timePassed) / 1e18 ) < 0` the transaction will be reverted and the user won't be able to unstake tokens.
There is a typo in the contract, the word `distirbuted` should be `distributed`: ```solidity=24 /// @notice Details for epoch /// @param totalToDistirbute Total amount of token to distirbute for epoch /// @param totalClaimed Total amount of tokens claimed from epoch /// @param startTime Timestamp epoch started /// @param endTime Timestamp epoch ends /// @param meanMultiplierAtEnd Mean multiplier at end of epoch /// @param weightAtEnd Weight of staked tokens at end of epoch struct Epoch { uint256 totalToDistirbute; uint256 totalClaimed; uint256 startTime; uint256 endTime; uint256 meanMultiplierAtEnd; uint256 weightAtEnd; } ``` ```solidity=116 function distirbute() public { ``` ```solidity=124 _epoch.totalToDistirbute = IERC20(rewardToken).balanceOf(address(this)) - unclaimedRewards; ``` ```solidity=131 unclaimedRewards += _epoch.totalToDistirbute; ``` ```solidity=140 distirbute(); ``` ```solidity=173 distirbute(); ``` ```solidity=208 uint256 _epochRewards = (_epoch.totalToDistirbute * _userWeightAtEpoch) / weightAtEpoch(_epochIds[i]); if (_epoch.totalClaimed + _epochRewards > _epoch.totalToDistirbute) { _epochRewards = _epoch.totalToDistirbute - _epoch.totalClaimed; ```
The return value of the transfer()/transferFrom() call is not checked. ```solidity=142 IERC20(pdt).transferFrom(msg.sender, address(this), _amount); ``` --- ```solidity=188 IERC20(pdt).transfer(_to, _amount); ``` --- ```solidity=218 IERC20(rewardToken).transfer(_to, _pendingRewards); ```
The contract has unlocked compiler version. An unlocked compiler version in the source code of the contract permits the user to compile it at or above a particular version. This, in turn, leads to differences in the generated bytecode between compilations due to differing compiler version numbers. This can lead to an ambiguity when debugging as compiler specific bugs may occur in the codebase that would be hard to identify over a span of multiple compiler versions rather than a specific one.
The report names a repository or files. Open the report to see its scope.
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