PolyReflect Staking - Smart Contract Audit Report
Summary
The PolyReflect team has built a yield farm and token with frictionless fee redistribution on Polygon.
For this audit we reviewed the project's staking contract and token contract at commit 0xa8c417708c9ba334c4701519942bf2b1ea9e49fb and again at commit 84075bd5f27ee64115e0ffdbaeea016960020c0f on GitHub.
Notes of the Token Contract:Notes of the Staking Contract:
- The total supply of the token is set to 10 billion.
- No mint or burn functions are present; though the circulating supply can be reduced by sending tokens to the 0x..dead address, if desired.
- The token is not yet deployed, so we are unable to provide insights into the token's allocation.
- Users who hold tokens will automatically receive a proportional amount of the 1% transaction tax incurred on each transfer.
- By default, users cannot trade the token and fees are disabled. Trading can begin and fees will be enabled when the owner calls unlockAfterPresale(). Once unlocked, it cannot be locked again.
- The owner can exclude and include accounts from the fee mechanism at any time.
- The contract utilizes SafeMath libraries to prevent overflows along with following the ERC20 standard.
Notes of the Deployer Contracts:
- Users can stake various tokens into the staking contract in order to earn PolyReflect tokens.
- There are no fees associated with making a deposit to the contract.
- The team must provide the reward tokens manually. The duration of the rewards period will be based on the number of tokens available in the contract and the emission rate which can be updated by the team.
- The project team can add different types of tokens for staking, and can update the reward rates for each token.
- Utilization of SafeMath (or similarily safe functions) to prevent overflow issues.
Audit Findings Summary
- The old Deployer contract was used for a previous presale where the softcap was not met.
- The DeployerV2 contract acts as a new presale contract for the project.
- Users have the option to purchase PRF tokens at the price of 8,000 PRF per MATIC invested.
- Users who participated in the previous presale can reap a bonus by participating in this presale.
- The soft cap for the sale is 250,000 MATIC, and the hard cap is 625,000.
- Each wallet address is only allowed to invest a maximum of 2,500 MATIC tokens.
- Any tokens not sold will be burned when the presale ends.
- The contract also includes a refund mechanism so the team can refund user's funds if desired.
- Utilization of SafeMath (or similarily safe functions) to prevent overflow issues.
- No issues from external attackers were identified.
- Ensure trust in the team as they have notable control in the ecosystem.
- Date: July 7th, 2021.
- Update Date: July 11th, 2021 - Fixes around transactions that could have exceeded the block.gaslimit; removal of some owner control.
- Update Date: July 15th, 2021 - Resolution of final outstanding issue.
External Threat Results
Vulnerability Category | Notes | Result |
---|---|---|
Arbitrary Storage Write | N/A | PASS |
Arbitrary Jump | N/A | PASS |
Delegate Call to Untrusted Contract | N/A | PASS |
Dependence on Predictable Variables | N/A | PASS |
Deprecated Opcodes | N/A | PASS |
Ether Thief | N/A | PASS |
Exceptions | N/A | PASS |
External Calls | N/A | PASS |
Flash Loans | N/A | PASS |
Integer Over/Underflow | N/A | PASS |
Multiple Sends | N/A | PASS |
Oracles | N/A | PASS |
Suicide | N/A | PASS |
State Change External Calls | N/A | PASS |
Unbounded Loops | N/A | PASS |
Unchecked Retval | N/A | PASS |
User Supplied Assertion | N/A | PASS |
Critical Solidity Compiler | N/A | PASS |
Overall Contract Safety | PASS |
Details: PRF Token
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Int] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ [Lib] SafeMath
- [Int] add
- [Int] sub
- [Int] sub
- [Int] mul
- [Int] div
- [Int] div
- [Int] mod
- [Int] mod
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Prv] _functionCallWithValue #
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ PolyReflect (Context, IERC20, Ownable)
- [Pub] #
- [Ext] setLPPair #
- [Ext] unlockAfterPresale #
- modifiers: onlyOwner
- [Pub] name
- [Pub] symbol
- [Pub] decimals
- [Pub] totalSupply
- [Pub] balanceOf
- [Pub] transfer #
- [Pub] allowance
- [Pub] approve #
- [Pub] transferFrom #
- [Pub] increaseAllowance #
- [Pub] increaseAllowanceFrom #
- modifiers: onlyOwner
- [Pub] decreaseAllowance #
- [Pub] isExcluded
- [Pub] totalFees
- [Pub] reflect #
- [Pub] reflectionFromToken
- [Pub] tokenFromReflection
- [Ext] excludeAccount #
- modifiers: onlyOwner
- [Ext] includeAccount #
- modifiers: onlyOwner
- [Prv] _approve #
- [Pub] transferNoFee #
- modifiers: allowedUser
- [Prv] _transfer #
- modifiers: lockedForPresale
- [Prv] _transferStandard #
- [Prv] _transferToExcluded #
- [Prv] _transferFromExcluded #
- [Prv] _transferBothExcluded #
- [Prv] _reflectFee #
- [Prv] _getValues
- [Prv] _getTValues
- [Prv] _getRValues
- [Prv] _getRate
- [Prv] _getCurrentSupply
Details: Staking
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Lib] SafeMath
- [Int] add
- [Int] sub
- [Int] sub
- [Int] mul
- [Int] div
- [Int] div
- [Int] mod
- [Int] mod
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ [Lib] EnumerableSet
- [Prv] _add #
- [Prv] _remove #
- [Prv] _contains
- [Prv] _length
- [Prv] _at
- [Int] add #
- [Int] remove #
- [Int] contains
- [Int] length
- [Int] at
- [Int] add #
- [Int] remove #
- [Int] contains
- [Int] length
- [Int] at
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Int] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ Staking (Ownable)
- [Pub] #
- [Ext] poolLength
- [Pub] fund #
- [Pub] add #
- modifiers: onlyOwner
- [Pub] set #
- modifiers: onlyOwner
- [Ext] deposited
- [Ext] pending
- [Ext] totalPending
- [Pub] massUpdatePools #
- [Pub] updatePool #
- [Pub] deposit #
- [Pub] withdraw #
- [Pub] emergencyWithdraw #
- [Int] erc20Transfer #
Details: Deployer
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Int] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Prv] _functionCallWithValue #
+ [Lib] SafeMath
- [Int] add
- [Int] sub
- [Int] sub
- [Int] mul
- [Int] div
- [Int] div
- [Int] mod
- [Int] mod
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Int] IQuickSwap
- [Ext] addLiquidityETH ($)
+ PolyReflect (Context, IERC20, Ownable)
- [Pub] #
- [Pub] name
- [Pub] symbol
- [Pub] decimals
- [Pub] totalSupply
- [Pub] balanceOf
- [Pub] transfer #
- [Pub] allowance
- [Pub] approve #
- [Pub] transferFrom #
- [Pub] increaseAllowance #
- [Pub] decreaseAllowance #
- [Pub] isExcluded
- [Pub] totalFees
- [Pub] reflect #
- [Pub] reflectionFromToken
- [Pub] tokenFromReflection
- [Ext] excludeAccount #
- modifiers: onlyOwner
- [Ext] includeAccount #
- modifiers: onlyOwner
- [Prv] _approve #
- [Ext] transferNoFee #
- modifiers: onlyOwner
- [Prv] _transfer #
- [Prv] _transferStandard #
- [Prv] _transferToExcluded #
- [Prv] _transferFromExcluded #
- [Prv] _transferBothExcluded #
- [Prv] _reflectFee #
- [Prv] _getValues
- [Prv] _getTValues
- [Prv] _getRValues
- [Prv] _getRate
- [Prv] _getCurrentSupply
+ Deployer (Context, Ownable)
- [Pub] #
- [Pub] _startTime
- [Pub] _totalRewards
- [Pub] adjustStart #
- modifiers: onlyOwner
- [Int] _getReward
- [Pub] endPresale #
- [Ext] withdraw #
- [Ext] ($)
Details: DeployerV2
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ [Int] IQuickSwap
- [Ext] addLiquidityETH ($)
- [Ext] WETH
+ [Int] IQuickSwapFactory
- [Ext] getPair
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Int] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ [Lib] SafeMath
- [Int] add
- [Int] sub
- [Int] sub
- [Int] mul
- [Int] div
- [Int] div
- [Int] mod
- [Int] mod
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Prv] _functionCallWithValue #
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ PolyReflect (Context, IERC20, Ownable)
- [Pub] #
- [Ext] setLPPair #
- [Ext] unlockAfterPresale #
- modifiers: onlyOwner
- [Pub] name
- [Pub] symbol
- [Pub] decimals
- [Pub] totalSupply
- [Pub] balanceOf
- [Pub] transfer #
- [Pub] allowance
- [Pub] approve #
- [Pub] transferFrom #
- [Pub] increaseAllowance #
- [Pub] increaseAllowanceFrom #
- modifiers: onlyOwner
- [Pub] decreaseAllowance #
- [Pub] isExcluded
- [Pub] totalFees
- [Pub] reflect #
- [Pub] reflectionFromToken
- [Pub] tokenFromReflection
- [Ext] excludeAccount #
- modifiers: onlyOwner
- [Ext] includeAccount #
- modifiers: onlyOwner
- [Prv] _approve #
- [Pub] transferNoFee #
- modifiers: allowedUser
- [Prv] _transfer #
- modifiers: lockedForPresale
- [Prv] _transferStandard #
- [Prv] _transferToExcluded #
- [Prv] _transferFromExcluded #
- [Prv] _transferBothExcluded #
- [Prv] _reflectFee #
- [Prv] _getValues
- [Prv] _getTValues
- [Prv] _getRValues
- [Prv] _getRate
- [Prv] _getCurrentSupply
+ [Lib] SafeMath
- [Int] add
- [Int] sub
- [Int] sub
- [Int] mul
- [Int] div
- [Int] div
- [Int] mod
- [Int] mod
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ [Lib] EnumerableSet
- [Prv] _add #
- [Prv] _remove #
- [Prv] _contains
- [Prv] _length
- [Prv] _at
- [Int] add #
- [Int] remove #
- [Int] contains
- [Int] length
- [Int] at
- [Int] add #
- [Int] remove #
- [Int] contains
- [Int] length
- [Int] at
+ Staking (Ownable)
- [Pub] #
- [Ext] poolLength
- [Pub] fund #
- [Pub] add #
- modifiers: onlyOwner
- [Pub] set #
- modifiers: onlyOwner
- [Ext] deposited
- [Ext] pending
- [Ext] totalPending
- [Pub] massUpdatePools #
- [Pub] updatePool #
- [Pub] deposit #
- [Pub] withdraw #
- [Pub] emergencyWithdraw #
- [Int] erc20Transfer #
+ [Int] DeployerV1
- [Ext] participants #
+ DeployerV2 (Context, Ownable)
- [Pub] ($)
- [Pub] _startTime
- [Pub] _endTime
- [Pub] _participantsLength
- [Pub] _totalRewards
- [Pub] adjustStart #
- modifiers: onlyOwner
- [Pub] adjustEnd #
- modifiers: onlyOwner
- [Int] _rewardFromMatic
- [Int] _maticFromReward
- [Int] addLiquidity #
- [Int] removeLiquidity #
- [Int] _getTokenAmountFromShare
- [Pub] endPresale #
- [Pub] withdraw #
- [Ext] ($)