ParagonsDAO - Audit

CertiKCode version: not recorded (see the report)

CertiK reviewed Paragons (ParagonsDAO - Audit) on 20 Sep 2022: 8 findings, 0 critical; 7 marked fixed, 1 open.

No open critical findings
Open the reportOpen Paragons’s security record

Report hosted on skynet.certik.com.

Trustblock does not review code.

Findings8

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

SeverityOpenAcknowledgedFixed
Critical000
High000
Medium001
Low106
MediumPotential Reentrancy Attack (Not Involving Ether)Fixed

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; ```

LowFunction Should Be Declared ExternalFixed

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_) { ```

LowMissing Zero Address ValidationFixed

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.

LowStaked tokens might become lockedFixed

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.

LowTypo In ContractFixed

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; ```

LowUnchecked ERC-20 `transfer()`/`transferFrom()` CaFixed

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); ```

LowUnlocked Compiler VersionFixed

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.

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.

Part of Paragons’s security record

Paragons
Audits2 audits by 2 firmsLast audit Nov 2023, by Quantstamp.
Critical findingsNo open critical findingsAcross 2 reports.
Open Paragons’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