GainPool - Smart Contract Audit Report

Summary

GainPool Audit Report GainPool is building a new yield farming platform where users can earn rewards in the form of the project's native GainCoin token.

For this audit, we analyzed GainPool's token contract and staking contract on the team's private Github Repository.

Notes on the Token Contract:
  • The initial total supply of the GainCoin token is 10 trillion [10,000,000,000,000] $GAIN.
  • Any user can burn their own tokens to reduce the total supply.
  • The contract utilizes a Minter role. Any assigned Minter address has the ability to mint any amount of tokens to any address at any time.
  • Although a Pauser role exists, it is never used within the contract.
  • The token complies with the ERC20 standard.
  • As the project is implemented with Solidity v0.8.0 it is protected from overflows.

  • Notes on the Staking Contract:
    • The owner has the ability to utilize this contract to create a staking pool. Users can stake their $GAIN tokens into the pool to earn $GAIN token rewards.
    • The team must exercise caution as to properly set the staking token and reward token as the $GAIN token.
    • Users can claim rewards when making a deposit to or a withdrawal from the contract. There is no fee associated with making a deposit or withdrawal.
    • Users can also manually claim all of their rewards via the claim() function.
    • The owner has the ability to update the rewards per block to any value greater than zero at any time.
    • The contract features an owner-specific function called destroy() that was not properly set by the team. This function will need to be properly set or removed as the contract cannot be deployed in its current state.
    • The contract utilizes SafeMath (and similarily safe functions) to prevent overflows.


    Audit Findings Summary:
    • No security issues from outside attackers were identified.
    • Please ensure trust in the team as they have some control in the ecosystem.
    • The team must properly set or remove the destroy() function in order for the staking contract to be deployable.
    • Date: October 19th, 2021

    Combined 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
    Logical IssuesStaking Contract does not compileFAIL
    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: GainPool- Token Contract


    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] 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] maxAmount
        - [Pub] balanceOf
        - [Pub] transfer #
        - [Pub] allowance
        - [Pub] approve #
        - [Pub] transferFrom #
        - [Pub] increaseAllowance #
        - [Pub] decreaseAllowance #
        - [Int] _transfer #
        - [Int] _mint #
        - [Int] _burn #
        - [Int] _approve #
        - [Int] _beforeTokenTransfer #
        - [Int] _afterTokenTransfer #
    
     +  ERC20Burnable (Context, ERC20)
        - [Pub] burn #
        - [Pub] burnFrom #
    
     +  Pausable (Context)
        - [Pub]  #
        - [Pub] paused
        - [Int] _pause #
           - modifiers: whenNotPaused
        - [Int] _unpause #
           - modifiers: whenPaused
    
     +  ERC20Pausable (ERC20, Pausable)
        - [Int] _beforeTokenTransfer #
    
     + [Int] IAccessControl 
        - [Ext] hasRole
        - [Ext] getRoleAdmin
        - [Ext] grantRole #
        - [Ext] revokeRole #
        - [Ext] renounceRole #
    
     + [Int] IAccessControlEnumerable (IAccessControl)
        - [Ext] getRoleMember
        - [Ext] getRoleMemberCount
    
     + [Lib] Strings 
        - [Int] toString
        - [Int] toHexString
        - [Int] toHexString
    
     + [Int] IERC165 
        - [Ext] supportsInterface
    
     +  ERC165 (IERC165)
        - [Pub] supportsInterface
    
     +  AccessControl (Context, IAccessControl, ERC165)
        - [Pub] supportsInterface
        - [Pub] hasRole
        - [Int] _checkRole
        - [Pub] getRoleAdmin
        - [Pub] grantRole #
           - modifiers: onlyRole
        - [Pub] revokeRole #
           - modifiers: onlyRole
        - [Pub] renounceRole #
        - [Int] _setupRole #
        - [Int] _setRoleAdmin #
        - [Prv] _grantRole #
        - [Prv] _revokeRole #
    
     + [Lib] EnumerableSet 
        - [Prv] _add #
        - [Prv] _remove #
        - [Prv] _contains
        - [Prv] _length
        - [Prv] _at
        - [Prv] _values
        - [Int] add #
        - [Int] remove #
        - [Int] contains
        - [Int] length
        - [Int] at
        - [Int] values
        - [Int] add #
        - [Int] remove #
        - [Int] contains
        - [Int] length
        - [Int] at
        - [Int] values
        - [Int] add #
        - [Int] remove #
        - [Int] contains
        - [Int] length
        - [Int] at
        - [Int] values
    
     +  AccessControlEnumerable (IAccessControlEnumerable, AccessControl)
        - [Pub] supportsInterface
        - [Pub] getRoleMember
        - [Pub] getRoleMemberCount
        - [Pub] grantRole #
        - [Pub] revokeRole #
        - [Pub] renounceRole #
        - [Int] _setupRole #
    
     +  ERC20PresetMinterPauser (Context, AccessControlEnumerable, ERC20Burnable, ERC20Pausable)
        - [Pub]  #
           - modifiers: ERC20
        - [Pub] mint #
        - [Pub] pause #
        - [Pub] unpause #
        - [Int] _beforeTokenTransfer #
    
     +  Gain (ERC20PresetMinterPauser)
        - [Pub]  #
           - modifiers: ERC20PresetMinterPauser


    Details: GainPool- Staking Contract


    Smart Contract Graph

    Smart Contract Inheritance

    
     ($) = payable function
     # = non-constant function
     
     Int = Internal
     Ext = External
     Pub = Public
    
     +  Context 
        - [Int] _msgSender
        - [Int] _msgData
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
    
     + [Int] IERC20 
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
    
     + [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
    
     + [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 #
    
     +  Stake (Ownable)
        - [Ext] setTokens #
           - modifiers: onlyOwner
        - [Ext] startPool #
           - modifiers: onlyOwner
        - [Ext] pendingRewards
        - [Int] updatePool #
        - [Ext] deposit #
        - [Ext] withdraw #
        - [Ext] claim #
        - [Int] safeTokenTransfer #
        - [Ext] setRewardPerBlock #
           - modifiers: onlyOwner
        - [Ext] destroy #
           - modifiers: onlyOwner