PayrLink - Smart Contract Audit Report
Summary
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 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 |
Integer Over/Underflow | N/A | PASS |
Multiple Sends | N/A | PASS |
Suicide | N/A | PASS |
State Change External Calls | 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: Crowdsale
($) = 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
($) = 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
($) = 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
($) = 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
($) = 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
($) = 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
($) = 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