Icarus Finance - Smart Contract Audit Report

Summary

Icarus Finance Audit Report Icarus is building a decentralized mining protocol to reward token holders to hashrates represented by the tokens.

We reviewed the Icarus Finance Token contract at 0x95111f630ac215eb74599ed42c67e2c2790d69e2 and the zETH contract at 0xdbeb98858f5d4dca13ea0272b2b786e9415d3992 on the Binance Smart Chain mainnet.
Please note we have not reviewed the project's staking contracts, or any other code.

Notes on the Contracts:

  • The total supply of the ICA token is 1 million with a supply cap of 10 million; while the total supply of ZETH is 400,000 with a supply cap of 1 million.
  • These tokens are minted upon deployment and sent to the team.
  • The team has the ability to mint tokens at any time. The team can also mint tokens to an address using a function which will lock the allocated tokens for a set period of time.
  • The token is designed to be a governance token where 1 token = 1 vote.
  • Another contract will be needed to collect votes and execute transactions on behalf of the DAO.
  • Token holders can delegate their voting rights to any address. To save gas, users can also do so using an EIP-712 signature.
  • Proper utilization of SafeMath to prevent overflows.

  • The team can mint tokens to an address in a manner where they are locked ('reserved') and unlock over time.
  • Users who have tokens in reserve via this method will have their tokens unlocked and able to claim gradually over time.
  • Claims of locked tokens shall be disabled for everyone except the owner until a time (set by the team) is reached.
  • The team can lock up ('reserve') tokens into the contract; though they can unlock them at any time.
  • The team can update this this at any time; and can also unstake locked funds on behalf of others, effectively allowing them to bypass the locking mechanism.
  • The team can reserve and un-reserve users' tokens for them without their permission via the reserve_from() and unreserve_from() functions. We advise removing these functions entirely.

  • The use of ReentrancyGuard on nearly every function is unnecessary and can be removed entirely to save on gas and deployment costs.
  • The logic in _beforeTokenTransfer and _afterTokenTransfer can be combined to reduce the number of internal calls and reap some gas savingss.
  • The team can update the name and symbol of the token as well. This should be removed as these variables should not change.
  • The can_claim() function performs a multiplication on the result of a division, leading to less accurate outputs. we advise rearranging the logic in lines 1437-1438.
  • A number of functions can be declared external instead of public to save gas on each call (List provided to the team).


  • Audit Findings Summary:
  • No security issues from outside attackers were identified.
  • As with any presale, ensure trust in the team prior to investing.
  • Furthermore, ensure trust in the team as they have notable power in the ecosystem.
  • KYC: No.
  • Date: March 26th, 2021.
  • 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

    Smart Contract Graph

    Contract Inheritance

    
     ($) = payable function
     # = non-constant function
     
     Int = Internal
     Ext = External
     Pub = Public
     
     + [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
    
     + [Int] IERC20 
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
    
     +  Context 
        - [Int] _msgSender
        - [Int] _msgData
    
     + [Lib] SafeERC20 
        - [Int] safeTransfer #
        - [Int] safeTransferFrom #
        - [Int] safeApprove #
        - [Int] safeIncreaseAllowance #
        - [Int] safeDecreaseAllowance #
        - [Prv] _callOptionalReturn #
    
     +  ReentrancyGuard 
        - [Int]  #
    
     +  StakingToken (Context, IERC20, ReentrancyGuard)
        - [Pub]  #
        - [Pub] transfer_ownership #
           - modifiers: owner_only,nonReentrant
        - [Pub] owner
        - [Pub] set_epoch #
           - modifiers: owner_only,nonReentrant
        - [Pub] mint_account
        - [Pub] name
        - [Pub] symbol
        - [Pub] decimals
        - [Pub] totalSupply
        - [Pub] cap
        - [Pub] softCap
        - [Pub] setSoftCap #
           - modifiers: owner_only,nonReentrant
        - [Pub] balanceOf
        - [Pub] setName #
           - modifiers: owner_only
        - [Pub] setSymbol #
           - modifiers: owner_only
        - [Pub] transfer #
           - modifiers: nonReentrant
        - [Pub] allowance
        - [Pub] approve #
           - modifiers: nonReentrant
        - [Pub] transferFrom #
           - modifiers: nonReentrant
        - [Pub] increaseAllowance #
           - modifiers: nonReentrant
        - [Pub] decreaseAllowance #
           - modifiers: nonReentrant
        - [Pub] mint #
           - modifiers: nonReentrant,mint_auth_required
        - [Pub] burn #
           - modifiers: nonReentrant
        - [Pub] burnFrom #
           - modifiers: nonReentrant
        - [Int] _transfer #
        - [Int] _mint #
        - [Int] _burn #
        - [Int] _approve #
        - [Int] _setupDecimals #
        - [Int] _beforeTokenTransfer #
        - [Int] _afterTokenTransfer #
        - [Int] _reserve #
        - [Int] _unreserve #
        - [Pub] reservedOf
        - [Pub] actualBalanceOf
        - [Pub] reserve_from #
           - modifiers: mint_auth_required,nonReentrant
        - [Pub] unreserve_from #
           - modifiers: mint_auth_required,nonReentrant
        - [Pub] set_mint_account #
           - modifiers: owner_only,nonReentrant
        - [Int] _moveDelegates #
        - [Int] _writeCheckpoint #
        - [Int] getChainId
        - [Pub] delegate #
           - modifiers: nonReentrant
        - [Ext] getCurrentVotes
        - [Pub] getPriorVotes
        - [Int] _delegate #
        - [Pub] mint_and_lock #
           - modifiers: mint_auth_required,nonReentrant
        - [Pub] can_claim
           - modifiers: isAlive
        - [Pub] claim #
           - modifiers: nonReentrant,isAlive
        - [Int] _transferToReserved #
        - [Int] _releaseBegins