PolyMaster

Smart Contract Audit Report

Audit Summary

PolyMaster is a new platform where users can stake PolyTokens in order to earn rewards.

For this audit, we reviewed the project team's PolyMaster, sPoly, and CHRStrategy contracts at commit dc9f1919e16e6a39fd7a789aa03b69069fc6e73c on the team's GitHub repository.

We previously reviewed the project team's staking platform here.

Audit Findings

Informational findings remain and the team should review these issues. In addition, centralized aspects are present.
The team has successfully completed KYC procedures with our firm.
Date: May 26th, 2023.
Updated: May 26th, 2023 to reflect changes from commit 93fa6bf96504d0528f72d424ba26b6174a471751 to commit dc9f1919e16e6a39fd7a789aa03b69069fc6e73c.
Updated: June 2nd, 2023 to reflect changes from commit dc9f1919e16e6a39fd7a789aa03b69069fc6e73c to commit dcd7f2521df6f9a53cc454d215f235f82495317b

Finding #1 - sPoly - High (Resolved)

Description: A user's lastClaimTime is not updated upon unstaking. As claim amounts are calculated using the following lines, users will be rewarded more PolyTokens than they are due upon claiming their locked PolyTokens.
function getClaimable(address user) public view returns (uint256 amount) {
	if (timeToFullClaim[user] > lastClaimedTime[user]) {
		return
			block.timestamp > timeToFullClaim[user]
				? claimablePerSecond[user] *
					(timeToFullClaim[user] - lastClaimedTime[user])
				: claimablePerSecond[user] *
					(block.timestamp - lastClaimedTime[user]);
	}
}
Risk/Impact: Users will receive more PolyTokens than intended each time a stake is claimed for the first time. This will withdraw other users' locked PolyTokens or cause claims to fail as there may not be a sufficient PolyToken balance in the contract.
Recommendation: The team should update a user's lastClaimTime upon unstaking.
Resolution: The team has implemented the above recommendation.

Finding #2 - CHRStrategy - Informational

Description: The withdraw() and emergencyWithdraw() functions execute the same functionality.
Recommendation: The emergencyWithdraw() function can be removed for gas savings on deployment and certain function calls. The PolyMaster's calls to the CHRStrategy's emergencyWithdraw() function should subsequently be updated for compatibility.
Resolution: The team has not yet addressed this issue.

Finding #3 - CHRStrategy - Informational

Description: The checkReward() function currently returns 0 instead of providing a user's pending rewards.
Recommendation: The checkReward() function should be updated to properly calculate a user's rewards, or both the checkReward() and pendingRewards(address user) functions should be removed for gas savings upon deployment and on function calls.
Resolution: The team has not yet addressed this issue.

Contracts Overview

  • As the contracts are implemented with Solidity v0.8, they are safe from any possible overflows/underflows.
  • The team must exercise caution when assigning the staking tokens to avoid using fee-on-transfer tokens and ERC-777 tokens.
PolyMaster Contract:
  • This contract allows Externally Owned Addresses (EOAs) and whitelisted contracts to stake tokens into various Pools to earn rewards in the project's native token.
  • Any address may deposit when the whitelist is not enabled.
  • Each Pool has its own staking token and Strategy contract associated with it.
  • All tokens staked into a Pool will be deposited in the corresponding Strategy.
  • A deposit fee may be taken and transferred to the Action Fee address controlled by the team if the Pool has a fee percentage set.
  • Users may optionally specify a referrer address if the EarningReferral fee has been set.
  • The EarningReferral contract is outside the scope of this audit so we are unable to give an assessment in regard to security.
  • Users will earn rewards over time based on the amount staked and the amount of points allocated to the pool.
  • Rewards will stop accumulating once the contract's "end time" is reached.
  • When a Pool's rewards are updated, an additional "dev percentage" of rewards tokens are transferred to the Dev address.
  • An additional fee may be taken from the tokens withdrawn from the associated Strategy contract during withdrawals if the Pool has withdrawal fees enabled.
  • The withdrawal fee will decrease over time from the last time the user withdrew from a Pool until reaching 0.
  • Users may harvest their rewards at any time. This will collect the user's rewards from this contract as well as any pending rewards from the Strategy contract.
  • If the harvesting user has supplied a referrer address, the referrer will be minted a "commission amount" of rewards tokens.
  • Only 30% of rewards are transferred to a user or referrer upon claiming. The remaining 70% is staked into the sPoly contract on behalf of the user, where the tokens can then be unlocked over time.
  • The user may also trigger an emergency withdrawal, which will withdraw all of the user's deposited tokens and forfeit any earned rewards.
  • The owner may add a new Pool at any time.
  • The owner may update a Pool's allocated points, deposit fee, and withdrawal fee at any time.
  • A pool's deposit or withdrawal fees can not exceed 4% each.
  • The owner may update the period of which the withdrawal fee decreases over at any time.
  • The owner may update the EarningReferral, Dev, and Action Fee addresses at any time.
  • The owner may update the Dev rate and rewards rate at any time.
  • The owner may add and remove any address from the whitelist at any time.
  • The owner may toggle whether contracts must be on the whitelist to deposit and withdraw at any time.
  • The owner may withdraw any errant tokens from a Strategy address at any time.
  • The owner may update a Strategy's token allowances at any time.
  • The owner may update a Strategy's performance fee basis points at any time.
  • The owner may update the commission amount percentage at any time.
  • The project team must ensure that the contract holds a sufficient PolyToken balance to supply reward distribution. If the contract does not hold a sufficient PolyToken balance, core contract functionality will fail.
sPoly Contract:
  • This contract allows users to lock PolyTokens into this contract where they can be gradually unlocked and withdrawn over a vesting period.
  • Upon depositing, the user is minted an equal amount in sPoly tokens to represent their deposited amount.
  • If the contract's withdrawal time has passed, users can initiate a withdrawal, where their tokens are then unlocked over the course of the contract's vesting period.
  • A user can claim any unlocked PolyTokens at any time.
  • If a user initiates a withdrawal before an existing withdrawal has fully vested, the existing withdrawal's remaining unvested amount is added to the new vesting schedule.
  • A user can alternatively instantly unstake if both the contract's withdrawal and instant withdrawal times have passed.
  • When instantly withdrawing, an instant withdrawal fee is taken from the withdrawal amount and transferred to the Withdrawal Fee Receiver address.
  • The owner can update the time at which users can withdraw at any time.
  • The owner can update the withdrawal and instant withdrawal times at any time.
  • The owner can update the instant withdrawal fee at any time.
  • The owner can update the Withdrawal Fee Receiver address at any time.
  • The owner can update the vesting period to any length at any time.
  • This contract complies with the ERC-20 standard.
CHRStrategy Contract:
  • This contract is intended to receive funds deposited into the PolyMaster contract and subsequently stake them into various associated Strategy contracts.
  • All rewards earned from associated Strategy contracts are transferred to a "Performance Fee address".
  • Only the owner, intended to be the PolyMaster contract, is permitted to deposit, withdraw, and emergency withdraw.
  • The deployer is set as the Admin upon deployment.
  • Ownership is transferred to the specified PolyMaster contract upon initialization.
  • When receiving a deposit, tokens are deposited into the Strategy contract associated with the pool.
  • Upon any standard or emergency withdrawal, any PolyMaster withdrawal fees are taken from the withdrawal amount and transferred to the PolyMaster's Action Fee Recipient address.
  • The remainder is transferred to the PolyMaster withdrawer's specified recipient.
  • Rewards from a pool's associated Strategy are harvested and transferred to the Performance Fee address upon any deposit, withdrawal, or emergency withdrawal. Any address can also manually harvest a pool's rewards to the Performance Fee address at any time.
  • As the associated Strategy contracts were not included within the scope of this audit, we are unable to provide an assessment with regards to security or functionality.
  • The Admin can update any pool's associated Strategy at any time.
  • The owner can withdraw any tokens from this contract to any address at any time.
  • The owner can grant the max allowance of a pool's token to its associated Strategy contract at any time.
  • The Admin can update the Performance Fee to any value at any time.
  • The Admin can update the Admin address at any time.

Audit Results

Vulnerability Category Notes Result
Arbitrary Jump/Storage Write N/A PASS
Centralization of Control
  • The owner and Admin Role have the permissions described above.
  • The owner can update the vesting period to any length at any time.
  • The owner can update the withdrawal and instant withdrawal timestamps at any time.
  • The Admin can update any pool's associated Strategy at any time.
  • WARNING
    Compiler Issues N/A PASS
    Delegate Call to Untrusted Contract N/A PASS
    Dependence on Predictable Variables N/A PASS
    Ether/Token Theft N/A PASS
    Flash Loans N/A PASS
    Front Running N/A PASS
    Improper Events N/A PASS
    Improper Authorization Scheme N/A PASS
    Integer Over/Underflow N/A PASS
    Logical Issues N/A PASS
    Oracle Issues N/A PASS
    Outdated Compiler Version N/A PASS
    Race Conditions N/A PASS
    Reentrancy N/A PASS
    Signature Issues N/A PASS
    Sybil Attack N/A PASS
    Unbounded Loops N/A PASS
    Unused Code
  • Various unused code as described in Findings #2 and #3.
  • PASS
    Overall Contract Safety   PASS

    PolyMaster Contract

    Smart Contract Audit - Inheritance

    Smart Contract Audit - Graph

    
    	 ($) = payable function
    	 # = non-constant function
    	 
    	 Int = Internal
    	 Ext = External
    	 Pub = Public
    	 +  Context 
    	 - [Int] _msgSender
    	 - [Int] _msgData
     
      +  Ownable (Context)
    	 - [Pub]  #
    	 - [Pub] owner
    	 - [Int] _checkOwner
    	 - [Pub] renounceOwnership #
    		- modifiers: onlyOwner
    	 - [Pub] transferOwnership #
    		- modifiers: onlyOwner
    	 - [Int] _transferOwnership #
     
      + [Int] IERC20 
    	 - [Ext] totalSupply
    	 - [Ext] balanceOf
    	 - [Ext] transfer #
    	 - [Ext] allowance
    	 - [Ext] approve #
    	 - [Ext] transferFrom #
     
      + [Int] IERC20Permit 
    	 - [Ext] permit #
    	 - [Ext] nonces
    	 - [Ext] DOMAIN_SEPARATOR
     
      + [Lib] Address 
    	 - [Int] isContract
    	 - [Int] sendValue #
    	 - [Int] functionCall #
    	 - [Int] functionCall #
    	 - [Int] functionCallWithValue #
    	 - [Int] functionCallWithValue #
    	 - [Int] functionStaticCall
    	 - [Int] functionStaticCall
    	 - [Int] functionDelegateCall #
    	 - [Int] functionDelegateCall #
    	 - [Int] verifyCallResultFromTarget
    	 - [Int] verifyCallResult
    	 - [Prv] _revert
     
      + [Lib] SafeERC20 
    	 - [Int] safeTransfer #
    	 - [Int] safeTransferFrom #
    	 - [Int] safeApprove #
    	 - [Int] safeIncreaseAllowance #
    	 - [Int] safeDecreaseAllowance #
    	 - [Int] forceApprove #
    	 - [Int] safePermit #
    	 - [Prv] _callOptionalReturn #
    	 - [Prv] _callOptionalReturnBool #
     
      + [Int] IERC20Metadata (IERC20)
    	 - [Ext] name
    	 - [Ext] symbol
    	 - [Ext] decimals
     
      +  ERC20 (Context, IERC20, IERC20Metadata)
    	 - [Pub]  #
    	 - [Pub] name
    	 - [Pub] symbol
    	 - [Pub] decimals
    	 - [Pub] totalSupply
    	 - [Pub] balanceOf
    	 - [Pub] transfer #
    	 - [Pub] allowance
    	 - [Pub] approve #
    	 - [Pub] transferFrom #
    	 - [Pub] increaseAllowance #
    	 - [Pub] decreaseAllowance #
    	 - [Int] _transfer #
    	 - [Int] _mint #
    	 - [Int] _burn #
    	 - [Int] _approve #
    	 - [Int] _spendAllowance #
    	 - [Int] _beforeTokenTransfer #
    	 - [Int] _afterTokenTransfer #
     
      + [Int] IERC20 
    	 - [Ext] totalSupply
    	 - [Ext] balanceOf
    	 - [Ext] transfer #
    	 - [Ext] allowance
    	 - [Ext] approve #
    	 - [Ext] transferFrom #
     
      + [Int] IPolyStrategy 
    	 - [Ext] deposit #
    	 - [Ext] withdraw #
    	 - [Ext] inCaseTokensGetStuck #
    	 - [Ext] setAllowances #
    	 - [Ext] revokeAllowance #
    	 - [Ext] migrate #
    	 - [Ext] onMigration #
    	 - [Ext] pendingTokens
    	 - [Ext] transferOwnership #
    	 - [Ext] setPerformanceFeeBips #
    	 - [Ext] emergencyWithdraw #
     
      + [Int] IEarningsReferral 
    	 - [Ext] recordReferral #
    	 - [Ext] recordReferralCommission #
    	 - [Ext] getReferrer
     
      + [Lib] Math 
    	 - [Int] max
    	 - [Int] min
    	 - [Int] average
    	 - [Int] ceilDiv
    	 - [Int] mulDiv
    	 - [Int] mulDiv
    	 - [Int] sqrt
    	 - [Int] sqrt
    	 - [Int] log2
    	 - [Int] log2
    	 - [Int] log10
    	 - [Int] log10
    	 - [Int] log256
    	 - [Int] log256
     
      + [Lib] SignedMath 
    	 - [Int] max
    	 - [Int] min
    	 - [Int] average
    	 - [Int] abs
     
      + [Lib] Strings 
    	 - [Int] toString
    	 - [Int] toString
    	 - [Int] toHexString
    	 - [Int] toHexString
    	 - [Int] toHexString
    	 - [Int] equal
     
      + [Lib] ECDSA 
    	 - [Prv] _throwError
    	 - [Int] tryRecover
    	 - [Int] recover
    	 - [Int] tryRecover
    	 - [Int] recover
    	 - [Int] tryRecover
    	 - [Int] recover
    	 - [Int] toEthSignedMessageHash
    	 - [Int] toEthSignedMessageHash
    	 - [Int] toTypedDataHash
    	 - [Int] toDataWithIntendedValidatorHash
     
      + [Lib] StorageSlot 
    	 - [Int] getAddressSlot
    	 - [Int] getBooleanSlot
    	 - [Int] getBytes32Slot
    	 - [Int] getUint256Slot
    	 - [Int] getStringSlot
    	 - [Int] getStringSlot
    	 - [Int] getBytesSlot
    	 - [Int] getBytesSlot
     
      + [Lib] ShortStrings 
    	 - [Int] toShortString
    	 - [Int] toString
    	 - [Int] byteLength
    	 - [Int] toShortStringWithFallback #
    	 - [Int] toStringWithFallback
    	 - [Int] byteLengthWithFallback
     
      + [Int] IERC5267 
    	 - [Ext] eip712Domain
     
      +  EIP712 (IERC5267)
    	 - [Pub]  #
    	 - [Int] _domainSeparatorV4
    	 - [Prv] _buildDomainSeparator
    	 - [Int] _hashTypedDataV4
    	 - [Pub] eip712Domain
     
      + [Lib] Counters 
    	 - [Int] current
    	 - [Int] increment #
    	 - [Int] decrement #
    	 - [Int] reset #
     
      +  ERC20Permit (ERC20, IERC20Permit, EIP712)
    	 - [Pub]  #
    		- modifiers: EIP712
    	 - [Pub] permit #
    	 - [Pub] nonces
    	 - [Ext] DOMAIN_SEPARATOR
    	 - [Int] _useNonce #
     
      +  PolyToken (ERC20Permit)
    	 - [Pub]  #
    		- modifiers: ERC20,ERC20Permit
     
      +  sPoly (ERC20, Ownable)
    	 - [Pub]  #
    		- modifiers: ERC20
    	 - [Pub] setVestingPeriod #
    		- modifiers: onlyOwner
    	 - [Pub] setWithdrawalEnabledTime #
    		- modifiers: onlyOwner
    	 - [Pub] setWithdrawalFeeRate #
    		- modifiers: onlyOwner
    	 - [Pub] setWithdrawalFeeReceiver #
    		- modifiers: onlyOwner
    	 - [Pub] setInstantWithdrawalEnabledTime #
    		- modifiers: onlyOwner
    	 - [Pub] stake #
    	 - [Pub] unstake #
    	 - [Pub] instantUnstake #
    	 - [Pub] claim #
    	 - [Pub] getClaimable
    	 - [Pub] getVestingAmount
     
      +  PolyMaster (Ownable)
    	 - [Ext] initialize #
    		- modifiers: onlyOwner
    	 - [Pub] poolLength
    	 - [Pub] pendingEarnings
    	 - [Ext] pendingTokens
    	 - [Pub] reward
    	 - [Pub] earningPerYear
    	 - [Pub] earningPerYearToMonopoly
    	 - [Pub] totalShares
    	 - [Pub] totalLP
    	 - [Pub] userShares
    	 - [Pub] updatePool #
    	 - [Pub] massUpdatePools #
    	 - [Ext] deposit #
    		- modifiers: onlyApprovedContractOrEOA
    	 - [Ext] withdraw #
    		- modifiers: onlyApprovedContractOrEOA
    	 - [Ext] harvest #
    		- modifiers: onlyApprovedContractOrEOA
    	 - [Ext] withdrawAndHarvest #
    		- modifiers: onlyApprovedContractOrEOA
    	 - [Ext] emergencyWithdraw #
    		- modifiers: onlyApprovedContractOrEOA
    	 - [Ext] add #
    		- modifiers: onlyOwner
    	 - [Ext] set #
    		- modifiers: onlyOwner
    	 - [Ext] setDev #
    		- modifiers: onlyOwner
    	 - [Ext] setPerfomanceFeeAddress #
    		- modifiers: onlyOwner
    	 - [Ext] setActionFeeAddress #
    		- modifiers: onlyOwner
    	 - [Ext] setDevMintBips #
    		- modifiers: onlyOwner
    	 - [Ext] setEarningsEmission #
    		- modifiers: onlyOwner
    	 - [Ext] modifyApprovedContracts #
    		- modifiers: onlyOwner
    	 - [Ext] setOnlyApprovedContractOrEOAStatus #
    		- modifiers: onlyOwner
    	 - [Ext] inCaseTokensGetStuck #
    		- modifiers: onlyOwner
    	 - [Ext] inCaseTokenGetStuck #
    		- modifiers: onlyOwner
    	 - [Ext] setAllowances #
    		- modifiers: onlyOwner
    	 - [Ext] revokeAllowance #
    		- modifiers: onlyOwner
    	 - [Ext] setPerformanceFeeBips #
    		- modifiers: onlyOwner
    	 - [Int] safeEarningsTransfer #
    	 - [Pub] getWithdrawFee
    	 - [Pub] setWithdrawalDuration #
    		- modifiers: onlyOwner
    	 - [Pub] setEarningsReferral #
    		- modifiers: onlyOwner
    	 - [Pub] setReferralCommissionRate #
    		- modifiers: onlyOwner
    	 - [Int] payReferralCommission #
     
     
    	
    		

    sPoly Contract

    Smart Contract Audit - Inheritance

    Smart Contract Audit - Graph

    
    	 ($) = 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 #
    
     + [Int] IERC20Permit 
        - [Ext] permit #
        - [Ext] nonces
        - [Ext] DOMAIN_SEPARATOR
    
     + [Lib] Address 
        - [Int] isContract
        - [Int] sendValue #
        - [Int] functionCall #
        - [Int] functionCall #
        - [Int] functionCallWithValue #
        - [Int] functionCallWithValue #
        - [Int] functionStaticCall
        - [Int] functionStaticCall
        - [Int] functionDelegateCall #
        - [Int] functionDelegateCall #
        - [Int] verifyCallResultFromTarget
        - [Int] verifyCallResult
        - [Prv] _revert
    
     + [Lib] SafeERC20 
        - [Int] safeTransfer #
        - [Int] safeTransferFrom #
        - [Int] safeApprove #
        - [Int] safeIncreaseAllowance #
        - [Int] safeDecreaseAllowance #
        - [Int] forceApprove #
        - [Int] safePermit #
        - [Prv] _callOptionalReturn #
        - [Prv] _callOptionalReturnBool #
    
     + [Int] IERC20Metadata (IERC20)
        - [Ext] name
        - [Ext] symbol
        - [Ext] decimals
    
     +  Context 
        - [Int] _msgSender
        - [Int] _msgData
    
     +  ERC20 (Context, IERC20, IERC20Metadata)
        - [Pub]  #
        - [Pub] name
        - [Pub] symbol
        - [Pub] decimals
        - [Pub] totalSupply
        - [Pub] balanceOf
        - [Pub] transfer #
        - [Pub] allowance
        - [Pub] approve #
        - [Pub] transferFrom #
        - [Pub] increaseAllowance #
        - [Pub] decreaseAllowance #
        - [Int] _transfer #
        - [Int] _mint #
        - [Int] _burn #
        - [Int] _approve #
        - [Int] _spendAllowance #
        - [Int] _beforeTokenTransfer #
        - [Int] _afterTokenTransfer #
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Int] _checkOwner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
        - [Int] _transferOwnership #
    
     +  sPoly (ERC20, Ownable)
        - [Pub]  #
           - modifiers: ERC20
        - [Pub] setVestingPeriod #
           - modifiers: onlyOwner
        - [Pub] setWithdrawalEnabledTime #
           - modifiers: onlyOwner
        - [Pub] setWithdrawalFeeRate #
           - modifiers: onlyOwner
        - [Pub] setWithdrawalFeeReceiver #
           - modifiers: onlyOwner
        - [Pub] setInstantWithdrawalEnabledTime #
           - modifiers: onlyOwner
        - [Pub] stake #
        - [Pub] unstake #
        - [Pub] instantUnstake #
        - [Pub] claim #
        - [Pub] getClaimable
        - [Pub] getVestingAmount
    
    		

    CHRStrategy Contract

    Smart Contract Audit - Inheritance

    Smart Contract Audit - Graph

    
    	 ($) = 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 #
    
     + [Int] IERC20Permit 
        - [Ext] permit #
        - [Ext] nonces
        - [Ext] DOMAIN_SEPARATOR
    
     + [Lib] Address 
        - [Int] isContract
        - [Int] sendValue #
        - [Int] functionCall #
        - [Int] functionCall #
        - [Int] functionCallWithValue #
        - [Int] functionCallWithValue #
        - [Int] functionStaticCall
        - [Int] functionStaticCall
        - [Int] functionDelegateCall #
        - [Int] functionDelegateCall #
        - [Int] verifyCallResultFromTarget
        - [Int] verifyCallResult
        - [Prv] _revert
    
     + [Lib] SafeERC20 
        - [Int] safeTransfer #
        - [Int] safeTransferFrom #
        - [Int] safeApprove #
        - [Int] safeIncreaseAllowance #
        - [Int] safeDecreaseAllowance #
        - [Int] forceApprove #
        - [Int] safePermit #
        - [Prv] _callOptionalReturn #
        - [Prv] _callOptionalReturnBool #
    
     +  Context 
        - [Int] _msgSender
        - [Int] _msgData
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Int] _checkOwner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
        - [Int] _transferOwnership #
    
     + [Int] IERC20Metadata (IERC20)
        - [Ext] name
        - [Ext] symbol
        - [Ext] decimals
    
     +  ERC20 (Context, IERC20, IERC20Metadata)
        - [Pub]  #
        - [Pub] name
        - [Pub] symbol
        - [Pub] decimals
        - [Pub] totalSupply
        - [Pub] balanceOf
        - [Pub] transfer #
        - [Pub] allowance
        - [Pub] approve #
        - [Pub] transferFrom #
        - [Pub] increaseAllowance #
        - [Pub] decreaseAllowance #
        - [Int] _transfer #
        - [Int] _mint #
        - [Int] _burn #
        - [Int] _approve #
        - [Int] _spendAllowance #
        - [Int] _beforeTokenTransfer #
        - [Int] _afterTokenTransfer #
    
     + [Int] IPolyStrategy 
        - [Ext] deposit #
        - [Ext] withdraw #
        - [Ext] inCaseTokensGetStuck #
        - [Ext] setAllowances #
        - [Ext] revokeAllowance #
        - [Ext] migrate #
        - [Ext] onMigration #
        - [Ext] pendingTokens
        - [Ext] transferOwnership #
        - [Ext] setPerformanceFeeBips #
        - [Ext] emergencyWithdraw #
    
     + [Int] IEarningsReferral 
        - [Ext] recordReferral #
        - [Ext] recordReferralCommission #
        - [Ext] getReferrer
    
     + [Lib] Math 
        - [Int] max
        - [Int] min
        - [Int] average
        - [Int] ceilDiv
        - [Int] mulDiv
        - [Int] mulDiv
        - [Int] sqrt
        - [Int] sqrt
        - [Int] log2
        - [Int] log2
        - [Int] log10
        - [Int] log10
        - [Int] log256
        - [Int] log256
    
     + [Lib] SignedMath 
        - [Int] max
        - [Int] min
        - [Int] average
        - [Int] abs
    
     + [Lib] Strings 
        - [Int] toString
        - [Int] toString
        - [Int] toHexString
        - [Int] toHexString
        - [Int] toHexString
        - [Int] equal
    
     + [Lib] ECDSA 
        - [Prv] _throwError
        - [Int] tryRecover
        - [Int] recover
        - [Int] tryRecover
        - [Int] recover
        - [Int] tryRecover
        - [Int] recover
        - [Int] toEthSignedMessageHash
        - [Int] toEthSignedMessageHash
        - [Int] toTypedDataHash
        - [Int] toDataWithIntendedValidatorHash
    
     + [Lib] StorageSlot 
        - [Int] getAddressSlot
        - [Int] getBooleanSlot
        - [Int] getBytes32Slot
        - [Int] getUint256Slot
        - [Int] getStringSlot
        - [Int] getStringSlot
        - [Int] getBytesSlot
        - [Int] getBytesSlot
    
     + [Lib] ShortStrings 
        - [Int] toShortString
        - [Int] toString
        - [Int] byteLength
        - [Int] toShortStringWithFallback #
        - [Int] toStringWithFallback
        - [Int] byteLengthWithFallback
    
     + [Int] IERC5267 
        - [Ext] eip712Domain
    
     +  EIP712 (IERC5267)
        - [Pub]  #
        - [Int] _domainSeparatorV4
        - [Prv] _buildDomainSeparator
        - [Int] _hashTypedDataV4
        - [Pub] eip712Domain
    
     + [Lib] Counters 
        - [Int] current
        - [Int] increment #
        - [Int] decrement #
        - [Int] reset #
    
     +  ERC20Permit (ERC20, IERC20Permit, EIP712)
        - [Pub]  #
           - modifiers: EIP712
        - [Pub] permit #
        - [Pub] nonces
        - [Ext] DOMAIN_SEPARATOR
        - [Int] _useNonce #
    
     +  PolyToken (ERC20Permit)
        - [Pub]  #
           - modifiers: ERC20,ERC20Permit
    
     +  sPoly (ERC20, Ownable)
        - [Pub]  #
           - modifiers: ERC20
        - [Pub] setVestingPeriod #
           - modifiers: onlyOwner
        - [Pub] setWithdrawalEnabledTime #
           - modifiers: onlyOwner
        - [Pub] setWithdrawalFeeRate #
           - modifiers: onlyOwner
        - [Pub] setWithdrawalFeeReceiver #
           - modifiers: onlyOwner
        - [Pub] setInstantWithdrawalEnabledTime #
           - modifiers: onlyOwner
        - [Pub] stake #
        - [Pub] unstake #
        - [Pub] instantUnstake #
        - [Pub] claim #
        - [Pub] getClaimable
        - [Pub] getVestingAmount
    
     +  PolyMaster (Ownable)
        - [Ext] initialize #
           - modifiers: onlyOwner
        - [Pub] poolLength
        - [Pub] pendingEarnings
        - [Ext] pendingTokens
        - [Pub] reward
        - [Pub] earningPerYear
        - [Pub] earningPerYearToMonopoly
        - [Pub] totalShares
        - [Pub] totalLP
        - [Pub] userShares
        - [Pub] updatePool #
        - [Pub] massUpdatePools #
        - [Ext] deposit #
           - modifiers: onlyApprovedContractOrEOA
        - [Ext] withdraw #
           - modifiers: onlyApprovedContractOrEOA
        - [Ext] harvest #
           - modifiers: onlyApprovedContractOrEOA
        - [Ext] withdrawAndHarvest #
           - modifiers: onlyApprovedContractOrEOA
        - [Ext] emergencyWithdraw #
           - modifiers: onlyApprovedContractOrEOA
        - [Ext] add #
           - modifiers: onlyOwner
        - [Ext] set #
           - modifiers: onlyOwner
        - [Ext] setDev #
           - modifiers: onlyOwner
        - [Ext] setPerfomanceFeeAddress #
           - modifiers: onlyOwner
        - [Ext] setActionFeeAddress #
           - modifiers: onlyOwner
        - [Ext] setDevMintBips #
           - modifiers: onlyOwner
        - [Ext] setEarningsEmission #
           - modifiers: onlyOwner
        - [Ext] modifyApprovedContracts #
           - modifiers: onlyOwner
        - [Ext] setOnlyApprovedContractOrEOAStatus #
           - modifiers: onlyOwner
        - [Ext] inCaseTokensGetStuck #
           - modifiers: onlyOwner
        - [Ext] inCaseTokenGetStuck #
           - modifiers: onlyOwner
        - [Ext] setAllowances #
           - modifiers: onlyOwner
        - [Ext] revokeAllowance #
           - modifiers: onlyOwner
        - [Ext] setPerformanceFeeBips #
           - modifiers: onlyOwner
        - [Int] safeEarningsTransfer #
        - [Pub] getWithdrawFee
        - [Pub] setWithdrawalDuration #
           - modifiers: onlyOwner
        - [Pub] setEarningsReferral #
           - modifiers: onlyOwner
        - [Pub] setReferralCommissionRate #
           - modifiers: onlyOwner
        - [Int] payReferralCommission #
    
     + [Int] IMaGauge 
        - [Ext] depositAll #
        - [Ext] deposit #
        - [Ext] withdrawAndHarvest #
        - [Ext] getAllReward #
        - [Ext] getReward #
        - [Ext] balanceOf
        - [Ext] balanceOfToken
        - [Ext] earned
        - [Ext] earned
    
     + [Int] ImaNFT 
        - [Ext] balanceOf
    
     + [Int] IERC721Receiver 
        - [Ext] onERC721Received #
    
     +  CHRStrategy (Ownable, IERC721Receiver)
        - [Pub]  #
        - [Ext] initialize #
           - modifiers: onlyAdmin
        - [Ext] updateStrategy #
           - modifiers: onlyAdmin
        - [Ext] setPerformanceFeeBips #
           - modifiers: onlyAdmin
        - [Pub] checkReward
        - [Pub] checkReward
        - [Pub] pendingRewards
        - [Pub] pendingRewards
        - [Ext] pendingTokens
        - [Ext] rewardTokens
        - [Ext] harvest #
        - [Ext] deposit #
           - modifiers: onlyOwner
        - [Ext] withdraw #
           - modifiers: onlyOwner
        - [Ext] emergencyWithdraw #
           - modifiers: onlyOwner
        - [Ext] setAllowances #
           - modifiers: onlyOwner
        - [Int] _claimRewards #
        - [Int] _harvest #
        - [Int] _safeRewardTokenTransfer #
        - [Ext] onERC721Received #
        - [Ext] inCaseTokensGetStuck #
           - modifiers: onlyOwner
    
    		

    About SourceHat

    SourceHat has quickly grown to have one of the most experienced and well-equipped smart contract auditing teams in the industry. Our team has conducted 1800+ solidity smart contract audits covering all major project types and protocols, securing a total of over $50 billion U.S. dollars in on-chain value!
    Our firm is well-reputed in the community and is trusted as a top smart contract auditing company for the review of solidity code, no matter how complex. Our team of experienced solidity smart contract auditors performs audits for tokens, NFTs, crowdsales, marketplaces, gambling games, financial protocols, and more!

    Contact us today to get a free quote for a smart contract audit of your project!

    What is a SourceHat Audit?

    Typically, a smart contract audit is a comprehensive review process designed to discover logical errors, security vulnerabilities, and optimization opportunities within code. A SourceHat Audit takes this a step further by verifying economic logic to ensure the stability of smart contracts and highlighting privileged functionality to create a report that is easy to understand for developers and community members alike.

    How Do I Interpret the Findings?

    Each of our Findings will be labeled with a Severity level. We always recommend the team resolve High, Medium, and Low severity findings prior to deploying the code to the mainnet. Here is a breakdown on what each Severity level means for the project:

    • High severity indicates that the issue puts a large number of users' funds at risk and has a high probability of exploitation, or the smart contract contains serious logical issues which can prevent the code from operating as intended.
    • Medium severity issues are those which place at least some users' funds at risk and has a medium to high probability of exploitation.
    • Low severity issues have a relatively minor risk association; these issues have a low probability of occurring or may have a minimal impact.
    • Informational issues pose no immediate risk, but inform the project team of opportunities for gas optimizations and following smart contract security best practices.