EVCoin Presale and Staking - Smart Contract Audit Report

Audit Summary

EV Staking Audit Report Everest is building a new ERC-20 token sale platform as well as a staking contract for users to deposit tokens and earn yield in addition to claiming Everest NFTs.

For this audit, we reviewed the project team's EVCoinStaking and HellFirePresale contracts provided to us by the team.

We previously reviewed the project team's original $EVCoin token contract here.

Audit Findings

Please ensure trust in the team prior to investing as they have substantial control in the ecosystem.
Date: February 1st, 2022.

Finding #1 - EVCoinStaking & HellFirePresale - Informational

Description: Several functions are declared public, but are never called internally. Several state variables can never be modified, but are not declared constant.
			
- EVCoinStaking: stake, withdraw, harvest, onERC721Received, encodePackedData, withdrawETH
- HellFirePresale: encodedPackedData, buyWithUSDT, claimToken, setSellStartDate, setSellEndDate, setClaimStartDate, setMaxMarketCap, setMinPerTransaction, setTokenPricePerUSDT, endSale, withdrawCollectedUSDT, withdrawCollectedAllUSDT, withdrawCollectedETH, withdrawUnsoldTokens
Recommendation: We recommend declaring these functions external for additional gas savings on each call.
Resolution: The team has declared these functions external.

Finding #2 - EVCoinStaking & HellFirePresale - Informational

Description: Several state variables can never be modified, but are not declared constant.
			
- EVCoinStaking: EVTotalSupply
- HellFirePresale: totalSold
Recommendation: We recommend declaring these state variables constant for additional gas savings on each call.
Resolution: The EVTotalSupply variable is now set dynamically to the total supply of the staking token.

Contracts Overview

  • The contracts utilize ReentrancyGuard to prevent against re-entrancy attacks in applicable functions.
  • As the contracts are implemented using Solidity v0.8.0, they are safe from any possible overflows/underflows.
EVCoinStaking Contract:
  • This contract allows users to stake a designated token into the contract in order to earn rewards in the form of a reward token determined by the project team until the total staked token limit in the contract is reached.
  • Any Signer can claim a presale NFT one time, through the use of a signed message.
  • Additionally, any Signer that also has tokens staked can claim one NFT at any time, through the use of a signed message.
  • On deposits and withdrawals, any pending rewards are calculated and transferred to the user unless the total reward supply has been depleted.
  • Reward amounts are calculated based on time staked, set reward rate, and total reward supply value.
  • The project team should not use the reward token as a staking token or else rewards could be funded with users' staked funds.
  • The user can trigger an emergency withdrawal, which will transfer all the user's deposited tokens to their wallet address, without calculating rewards.

  • The owner is granted the Signer role upon deployment.
  • The owner can grant or revoke the Signer role from any address at any time.
  • Any user granted the Signer role can grant other addresses the Signer role at any time.
  • The owner can withdraw any tokens or ETH from the contract at any time.
  • The owner can change the reward rate at any time.
  • The owner can set the reward token address at any time.
  • The owner can set the staking limit to any value at any time.
  • The owner can transfer ownership to another address at any time.
  • The team must exercise caution when assigning the staking token to avoid using fee-on-transfer tokens.
HellFirePresale Contract:
  • This contract allows eligible users to purchase a specified ERC-20 token, determined by the team, using a predefined price in USDT.
  • Eligible users can purchase tokens through verification of a signed message while the sale is active until the maximum token amount has been reached. The purchase amount must be over the minimum transaction amount.
  • Users can then claim portions of their purchased tokens once the sale period has ended and the claiming period has started.
  • During the claiming period, users can claim 40% of their tokens within the first 14 days, 80% after 14 days, and 100% after 21 days.

  • The owner can start/end the sale at any time.
  • The owner can set the claiming period start date to any value, at any time.
  • The owner can change the maximum token amount to any value at any time.
  • The owner can set the token price in USDT to any value at any time.
  • The owner can set the minimum transaction amount to any value at any time.
  • The owner can withdraw any USDT tokens, presale tokens, or ETH stored in the contract at any time.

External Threat Results

Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Centralization of Control
  • The owner has the ownership controls described above.
  • Signed messages require the use of off-chain logic.
  • WARNING
    Delegate Call to Untrusted ContractN/APASS
    Dependence on Predictable VariablesN/APASS
    Deprecated OpcodesN/APASS
    Ether ThiefN/APASS
    ExceptionsN/APASS
    External CallsN/APASS
    Flash LoansN/APASS
    Integer Over/UnderflowN/APASS
    Logical IssuesN/APASS
    Multiple SendsN/APASS
    OraclesN/APASS
    SuicideN/APASS
    State Change External CallsN/APASS
    Unchecked RetvalN/APASS
    User Supplied AssertionN/APASS
    Critical Solidity CompilerN/APASS
    Overall Contract Safety PASS

    EVCoinStaking Contract

    BEP20 Token Graph

    Multi-file Token

    												
    ($) = payable function
     # = non-constant function
    
    + [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] 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 #
        - [Int] _grantRole #
        - [Int] _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
        - [Int] _grantRole #
        - [Int] _revokeRole #
    
     +  ERC20PresetMinterPauser (Context, AccessControlEnumerable, ERC20Burnable, ERC20Pausable)
        - [Pub]  #
           - modifiers: ERC20
        - [Pub] mint #
        - [Pub] pause #
        - [Pub] unpause #
        - [Int] _beforeTokenTransfer #
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
        - [Int] _transferOwnership #
    
     +  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
    
     + [Int] IERC721 (IERC165)
        - [Ext] balanceOf
        - [Ext] ownerOf
        - [Ext] safeTransferFrom #
        - [Ext] transferFrom #
        - [Ext] approve #
        - [Ext] getApproved
        - [Ext] setApprovalForAll #
        - [Ext] isApprovedForAll
        - [Ext] safeTransferFrom #
    
     + [Int] IERC721Receiver 
        - [Ext] onERC721Received #
    
     + [Lib] Address 
        - [Int] isContract
        - [Int] sendValue #
        - [Int] functionCall #
        - [Int] functionCall #
        - [Int] functionCallWithValue #
        - [Int] functionCallWithValue #
        - [Int] functionStaticCall
        - [Int] functionStaticCall
        - [Int] functionDelegateCall #
        - [Int] functionDelegateCall #
        - [Int] verifyCallResult
    
     + [Lib] SafeERC20 
        - [Int] safeTransfer #
        - [Int] safeTransferFrom #
        - [Int] safeApprove #
        - [Int] safeIncreaseAllowance #
        - [Int] safeDecreaseAllowance #
        - [Prv] _callOptionalReturn #
    
     + [Lib] Roles 
        - [Int] add #
        - [Int] remove #
        - [Int] has
    
     +  SignerRole (Context)
        - [Pub]  #
        - [Pub] isSigner
        - [Pub] addSigner #
           - modifiers: onlySigner
        - [Pub] renounceSigner #
        - [Int] _addSigner #
        - [Int] _removeSigner #
    
     + [Int] IMarketPlace721 
        - [Ext] mintBulkTokens #
    
     +  EVCoinStaking (ReentrancyGuard, Pausable, Ownable, SignerRole, IERC721Receiver)
        - [Pub]  #
        - [Ext] userStakeInfo
        - [Ext] setRewardTokenAddress #
           - modifiers: onlyOwner
        - [Ext] setRewardPerWeek #
           - modifiers: onlyOwner
        - [Ext] setStakLimit #
           - modifiers: onlyOwner
        - [Pub] stake #
           - modifiers: nonReentrant,whenNotPaused
        - [Pub] withdraw #
           - modifiers: nonReentrant
        - [Ext] emergencyWithdraw #
           - modifiers: nonReentrant
        - [Ext] pendingReward
        - [Int] _updatePool #
        - [Pub] harvest #
           - modifiers: nonReentrant
        - [Pub] onERC721Received #
        - [Pub] encodePackedData
        - [Ext] claimPresaleNFT #
        - [Ext] claimSatkeNFT #
        - [Ext] addSignerRole #
           - modifiers: onlyOwner
        - [Ext] removeSignerRole #
           - modifiers: onlyOwner
        - [Int] toEthSignedMessageHash
        - [Ext] recoverWrongTokens #
           - modifiers: onlyOwner
        - [Pub] withdrawETH #
           - modifiers: onlyOwner
    
     

    HellFirePresale Contract

    BEP20 Token Graph

    Multi-file Token

    												
    ($) = payable function
     # = non-constant function
     
    + [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] 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 #
        - [Int] _grantRole #
        - [Int] _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
        - [Int] _grantRole #
        - [Int] _revokeRole #
    
     +  ERC20PresetMinterPauser (Context, AccessControlEnumerable, ERC20Burnable, ERC20Pausable)
        - [Pub]  #
           - modifiers: ERC20
        - [Pub] mint #
        - [Pub] pause #
        - [Pub] unpause #
        - [Int] _beforeTokenTransfer #
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
        - [Int] _transferOwnership #
    
     +  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
    
     + [Lib] Address 
        - [Int] isContract
        - [Int] sendValue #
        - [Int] functionCall #
        - [Int] functionCall #
        - [Int] functionCallWithValue #
        - [Int] functionCallWithValue #
        - [Int] functionStaticCall
        - [Int] functionStaticCall
        - [Int] functionDelegateCall #
        - [Int] functionDelegateCall #
        - [Int] verifyCallResult
    
     + [Lib] SafeERC20 
        - [Int] safeTransfer #
        - [Int] safeTransferFrom #
        - [Int] safeApprove #
        - [Int] safeIncreaseAllowance #
        - [Int] safeDecreaseAllowance #
        - [Prv] _callOptionalReturn #
    
     + [Lib] Roles 
        - [Int] add #
        - [Int] remove #
        - [Int] has
    
     +  SignerRole (Context)
        - [Pub]  #
        - [Pub] isSigner
        - [Pub] addSigner #
           - modifiers: onlySigner
        - [Pub] renounceSigner #
        - [Int] _addSigner #
        - [Int] _removeSigner #
    
     +  HellFirePresale (ReentrancyGuard, Pausable, Ownable, SignerRole)
        - [Pub]  #
        - [Pub] encodePackedData
        - [Int] toEthSignedMessageHash
        - [Pub] buyWithUSDT ($)
           - modifiers: checkSaleRequirements,nonReentrant
        - [Pub] claimToken #
           - modifiers: nonReentrant
        - [Pub] setSellStartDate #
           - modifiers: onlyOwner
        - [Pub] setSellEndDate #
           - modifiers: onlyOwner
        - [Pub] setClaimStartDate #
           - modifiers: onlyOwner
        - [Pub] setMaxMarketCap #
           - modifiers: onlyOwner
        - [Pub] setMinPerTransaction #
           - modifiers: onlyOwner
        - [Pub] setTokenPricePerUSDT #
           - modifiers: onlyOwner
        - [Pub] endSale #
           - modifiers: onlyOwner
        - [Pub] withdrawCollectedUSDT #
           - modifiers: onlyOwner
        - [Pub] withdrawCollectedAllUSDT #
           - modifiers: onlyOwner
        - [Pub] withdrawCollectedETH #
           - modifiers: onlyOwner
        - [Pub] withdrawUnsoldTokens #
           - modifiers: onlyOwner
        - [Pub] unsoldTokens
        - [Pub] calculateUSDTAmount