PayrLink - Smart Contract Audit Report

Summary

PayrLink PayrLink is building a secure escrow service and private solution powered by blockchain technology.

We reviewed PayrLink's contracts at commit 6c1270e9a92316e4470ae784763117e87d544ccc and again at commit 74aca442c28544e9e83f7fbcd0893cc994f7b353 on GitHub.

Notes on the PAYR Token Contract:
  • The initial total supply is 200,000,000.
  • The owner can mint tokens at any time.
  • No other ownership-restricted functions are present.
  • No special transfer logic is present.
  • SafeMath is utilized to prevent overflows.

  • Notes on the Presale & Crowdsale Contracts:
  • This contract allows users to purchase tokens at a pre-determined price.
  • Users can contribute between 0.2 and 2 ETH to the presale.
  • Users will be able to claim their purchased tokens after the presale concludes.
  • The invest() function does not disable purchaes until the hard cap is met or exceeded. For any over-investments in the last purchase, the team will have to provide tokens to cover the excess; otherwise the last users to claim may be unable to do so.
  • At the conclusion of the presale, the team can can collect all of the funds raised as well as any tokens in the contract.
  • Ensure trust in the team as participation in the presale requies sending funds directly to the team's control.
  • The contract utilizes SafeMath for overflow checks and ReentrancyGuard is also used to prevent any potential reentrancy issues.

  • Notes on the Farm and PayrLink Staking Contracts:
  • Users can stake various tokens in these contract to earn rewards in the form of tokens.
  • The team will set the reward rate upon adding an asset pool.
  • The team must provide the reward tokens manually.
  • The duration of rewards can be extened if the team provides more reward tokens to the contract.
  • The team must exercise caution to not add the same asset pools multiple times.
  • Utilization of SafeMath to prevent overflow issues.

  • Notes on the ERC20Factory & ETHFactory Contracts:
  • These contracts are designed to operate as the core of the PayrLink escrow service.
  • Users can deposit funds into these contracts with a queued transaction to send them to a recipient.
  • The depositer can call a function to release the funds to the recipient.
  • Funds will be held in the contract and withdrawable by the depositer until they are released to the recipient.
  • Once a user recieves funds, they must go to the contract and call a function to withdraw them.
  • Logic is properly structured to prevent reentrancy and SafeMath is utilized to prevent overflow issues.


  • Audit Findings Summary:
    • No issues from external attackers were identified.
    • As with any presale, ensure trust in the project team prior to investing. The team is anonymous and will directly receive the raised funds.
    • Further, ensure trust in the team as they have substantial control in the ecosystem via their ability to mint tokens and modify farming rewards.
    • The team has worked with us to resolve a variety of issues and implement gas optimizations across these contracts.
    • Date: May 12th, 2021

    External Threat Results

    Vulnerability CategoryNotesResult
    Arbitrary Storage WriteN/APASS
    Arbitrary JumpN/APASS
    Delegate Call to Untrusted ContractN/APASS
    Dependence on Predictable VariablesN/APASS
    Deprecated OpcodesN/APASS
    Ether ThiefN/APASS
    ExceptionsN/APASS
    External CallsN/APASS
    Integer Over/UnderflowN/APASS
    Multiple SendsN/APASS
    SuicideN/APASS
    State Change External CallsN/APASS
    Unchecked RetvalN/APASS
    User Supplied AssertionN/APASS
    Critical Solidity CompilerN/APASS
    Overall Contract Safety PASS


    Details: Crowdsale

    Smart Contract Graph

    Smart Contract Inheritance

    
    
     ($) = payable function
     # = non-constant function
     
     Int = Internal
     Ext = External
     Pub = Public
      
     + [Int] IPAYR 
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
    
     +  Context 
        - [Int] _msgSender
        - [Int] _msgData
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
    
     +  ReentrancyGuard 
        - [Pub]  #
    
     + [Lib] SafeMath 
        - [Int] tryAdd
        - [Int] trySub
        - [Int] tryMul
        - [Int] tryDiv
        - [Int] tryMod
        - [Int] add
        - [Int] sub
        - [Int] mul
        - [Int] div
        - [Int] mod
        - [Int] sub
        - [Int] div
        - [Int] mod
    
     +  Crowdsale (Ownable, ReentrancyGuard)
        - [Pub]  #
        - [Ext]  ($)
        - [Ext] checkFunds
        - [Ext] checkPAYRFunds
        - [Ext] getETHBalance
        - [Ext] getCurrentPrice
        - [Pub] invest ($)
        - [Ext] getPAYR #
           - modifiers: afterClosed,nonReentrant
        - [Ext] withdrawETH #
           - modifiers: onlyOwner,afterClosed
        - [Ext] withdrawPAYR #
           - modifiers: onlyOwner,afterClosed


    Details: ERC20Factory

    Smart Contract Graph

    Smart Contract Inheritance

    
    
     ($) = 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] IPayrLink 
        - [Ext] poolLength
        - [Ext] addReward #
        - [Ext] deposited
        - [Ext] pending
        - [Ext] massUpdatePools #
        - [Ext] deposit #
        - [Ext] withdraw #
        - [Ext] emergencyWithdraw #
    
     +  Context 
        - [Int] _msgSender
        - [Int] _msgData
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
    
     +  ReentrancyGuard 
        - [Pub]  #
    
     +  ERC20Factory (Ownable, ReentrancyGuard)
        - [Pub]  #
        - [Ext] balanceOf
        - [Ext] pendingFromIds
        - [Ext] pendingToIds
        - [Ext] deposit #
           - modifiers: nonReentrant
        - [Ext] updatePoolId #
           - modifiers: onlyOwner
        - [Ext] withdraw #
           - modifiers: nonReentrant
        - [Ext] send #
        - [Ext] release #
        - [Int] removeFromPending #
        - [Ext] getFund #


    Details: ETHFactory

    Smart Contract Graph

    Smart Contract Inheritance

    
    
     ($) = 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] IPayrLink 
        - [Ext] poolLength
        - [Ext] addReward #
        - [Ext] deposited
        - [Ext] pending
        - [Ext] massUpdatePools #
        - [Ext] deposit #
        - [Ext] withdraw #
        - [Ext] emergencyWithdraw #
    
     +  Context 
        - [Int] _msgSender
        - [Int] _msgData
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
    
     +  ReentrancyGuard 
        - [Pub]  #
    
     +  ETHFactory (Ownable, ReentrancyGuard)
        - [Pub]  #
        - [Ext] balanceOf
        - [Ext] pendingFromIds
        - [Ext] pendingToIds
        - [Ext] deposit ($)
           - modifiers: nonReentrant
        - [Ext] updatePoolId #
           - modifiers: onlyOwner
        - [Ext] withdraw #
           - modifiers: nonReentrant
        - [Ext] send #
        - [Ext] release #
        - [Int] removeFromPending #
        - [Ext] getFund #
    


    Details: Farm

    Smart Contract Graph

    Smart Contract Inheritance

    
    
     ($) = payable function
     # = non-constant function
     
     Int = Internal
     Ext = External
     Pub = Public
    
     + [Int] IPAYR 
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
    
     + [Int] IERC20 
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
    
     + [Lib] Address 
        - [Int] isContract
        - [Int] sendValue #
        - [Int] functionCall #
        - [Int] functionCall #
        - [Int] functionCallWithValue #
        - [Int] functionCallWithValue #
        - [Int] functionStaticCall
        - [Int] functionStaticCall
        - [Int] functionDelegateCall #
        - [Int] functionDelegateCall #
        - [Prv] _verifyCallResult
    
     + [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
        - [Int] add #
        - [Int] remove #
        - [Int] contains
        - [Int] length
        - [Int] at
    
     + [Lib] SafeMath 
        - [Int] tryAdd
        - [Int] trySub
        - [Int] tryMul
        - [Int] tryDiv
        - [Int] tryMod
        - [Int] add
        - [Int] sub
        - [Int] mul
        - [Int] div
        - [Int] mod
        - [Int] sub
        - [Int] div
        - [Int] mod
    
     +  Context 
        - [Int] _msgSender
        - [Int] _msgData
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
    
     +  Farm (Ownable)
        - [Pub]  #
        - [Ext] poolLength
        - [Ext] fund #
           - modifiers: onlyOwner
        - [Ext] add #
           - modifiers: onlyOwner
        - [Ext] set #
           - modifiers: onlyOwner
        - [Ext] deposited
        - [Ext] pending
        - [Ext] totalPending
        - [Pub] massUpdatePools #
        - [Pub] updatePool #
        - [Ext] deposit #
        - [Ext] withdraw #
        - [Ext] emergencyWithdraw #
        - [Int] erc20Transfer #
        - [Ext] erc20Withdraw #
           - modifiers: onlyOwner
        - [Ext] ethWithdraw #
           - modifiers: onlyOwner


    Details: PAYR

    Smart Contract Graph

    Smart Contract Inheritance

    
    
     ($) = payable function
     # = non-constant function
     
     Int = Internal
     Ext = External
     Pub = Public
    
      + [Int] IPAYR 
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
    
     +  Context 
        - [Int] _msgSender
        - [Int] _msgData
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
    
     +  PAYR (Ownable, IPAYR)
        - [Pub]  #
        - [Ext] name
        - [Ext] symbol
        - [Ext] decimals
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
        - [Ext] increaseAllowance #
        - [Ext] decreaseAllowance #
        - [Int] _transfer #
        - [Ext] mint #
           - modifiers: onlyOwner
        - [Ext] burn #
           - modifiers: onlyOwner
        - [Int] _approve #


    Details: PayrLink

    Smart Contract Graph

    Smart Contract Inheritance

    
    
     ($) = payable function
     # = non-constant function
     
     Int = Internal
     Ext = External
     Pub = Public
    
     + [Int] IPAYR 
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
    
     + [Int] IERC20 
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
    
     + [Int] IPayrLink 
        - [Ext] poolLength
        - [Ext] addReward #
        - [Ext] deposited
        - [Ext] pending
        - [Ext] massUpdatePools #
        - [Ext] deposit #
        - [Ext] withdraw #
        - [Ext] emergencyWithdraw #
    
     + [Lib] Address 
        - [Int] isContract
        - [Int] sendValue #
        - [Int] functionCall #
        - [Int] functionCall #
        - [Int] functionCallWithValue #
        - [Int] functionCallWithValue #
        - [Int] functionStaticCall
        - [Int] functionStaticCall
        - [Int] functionDelegateCall #
        - [Int] functionDelegateCall #
        - [Prv] _verifyCallResult
    
     + [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
        - [Int] add #
        - [Int] remove #
        - [Int] contains
        - [Int] length
        - [Int] at
    
     + [Lib] SafeMath 
        - [Int] tryAdd
        - [Int] trySub
        - [Int] tryMul
        - [Int] tryDiv
        - [Int] tryMod
        - [Int] add
        - [Int] sub
        - [Int] mul
        - [Int] div
        - [Int] mod
        - [Int] sub
        - [Int] div
        - [Int] mod
    
     +  Context 
        - [Int] _msgSender
        - [Int] _msgData
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
    
     +  ReentrancyGuard 
        - [Pub]  #
    
     +  PayrLink (Ownable, IPayrLink, ReentrancyGuard)
        - [Pub]  #
        - [Ext] poolLength
        - [Ext] addEthPool #
           - modifiers: onlyOwner
        - [Ext] addERC20Pool #
           - modifiers: onlyOwner
        - [Ext] addReward #
        - [Ext] deposited
        - [Ext] pending
        - [Pub] massUpdatePools #
        - [Pub] updatePool #
        - [Ext] deposit #
           - modifiers: nonReentrant
        - [Ext] withdraw #
           - modifiers: nonReentrant
        - [Ext] emergencyWithdraw #
        - [Int] erc20Transfer #
    


    Details: Presale

    Smart Contract Graph

    Smart Contract Inheritance

    
    
     ($) = payable function
     # = non-constant function
     
     Int = Internal
     Ext = External
     Pub = Public
    
     + [Int] IPAYR 
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
    
     +  Context 
        - [Int] _msgSender
        - [Int] _msgData
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
    
     +  ReentrancyGuard 
        - [Pub]  #
    
     + [Lib] SafeMath 
        - [Int] tryAdd
        - [Int] trySub
        - [Int] tryMul
        - [Int] tryDiv
        - [Int] tryMod
        - [Int] add
        - [Int] sub
        - [Int] mul
        - [Int] div
        - [Int] mod
        - [Int] sub
        - [Int] div
        - [Int] mod
    
     +  Presale (Ownable, ReentrancyGuard)
        - [Pub]  #
        - [Ext]  ($)
        - [Ext] checkFunds
        - [Ext] checkPAYRFunds
        - [Ext] getETHBalance
        - [Pub] invest ($)
        - [Ext] getPAYR #
           - modifiers: afterClosed,nonReentrant
        - [Ext] withdrawETH #
           - modifiers: onlyOwner,afterClosed
        - [Ext] withdrawPAYR #
           - modifiers: onlyOwner,afterClosed