AstroFarm - Audit Report

Audit Summary

AstroFarm Audit Report AstroSwap is creating two new tokens and a staking contract in which users can earn rewards in the form of AstroTokens.

For this audit, we reviewed the AstroToken, AstroStake, and AstroFarm contracts at commit 772f4a4f9b85b5e14accc37850f007215a3653c4 on the team's GitHub repository.

Audit Findings

Please ensure trust in the team prior to investing as they have substantial control in the ecosystem.
Date: January 25th, 2022.

Finding #1 - AstroToken & AstroStake - High

Description: Token transfers do not transfer delegates along with the token.
Risk/Impact: Delegatees will retain their votes even if a transfer occurs. This can result in additional votes being created through the use of transfers.
Recommendation: The transfer functions should be overridden to add the appropriate _moveDelegates() calls.

Finding #2 - AstroToken - High

Description: Delegates are not moved when a user burns their own tokens.
			
function burn(uint256 _amount) public {
	_burn(msg.sender, _amount);
}

Risk/Impact: Votes will not be reduced if tokens are burned.
Recommendation: The following line should be added to the end of the above burn() function:
_moveDelegates(delegates[msg.sender], address(0), amount);

Finding #3 - AstroFarm - Informational

Description: The following functions are declared public, but are never called internally:
			
updateMultiplier(), add(), set(), setMigrator(), migrate(), deposit(), withdraw(), enterStaking(), leaveStaking(), emergencyWithdraw()
Recommendation: These functions can be declared external for additional gas savings.

Finding #4 - AstroFarm - Informational

Description: The "devaddr" variable and the dev() function are never used.
Recommendation: These can be removed for additional gas savings.

Contracts Overview

AstroToken Contract:
  • The owner can mint any number of $ASTRO tokens to any address at any time.
  • Users can burn their tokens to reduce total supply, if desired.
  • Each $ASTRO token represents votes intended to be used in a DAO where one token represents one vote.
  • Users may delegate their votes to another address allowing them to vote on behalf of the user.
  • Once votes are delegated, the user must explicitly delegate back to themselves to regain their votes.
  • Users also have the option to delegate through the use of a signed message, allowing for a gasless delegation for the user.
AstroStake Contract:
  • The owner can mint any number of AstroStake tokens to any address at any time.
  • The owner can also burn any users' tokens at any time.
  • Users can transfer their AstroStake tokens to the 0x..dead address to reduce circulating supply, if desired.
  • Each AstroStake token represents votes intended to be used in a DAO where one token represents one vote.
  • Users may delegate their votes to another address allowing them to vote on behalf of the user.
  • Once votes are delegated, the user must explicitly delegate back to themselves to regain their votes.
  • Users also have the option to delegate through the use of a signed message, allowing for a gasless delegation for the user.
  • The owner can transfer any amount of AstroTokens present in this contract to any address at any time.
  • Upon deployment, the owner is given the Operator role, allowing them to withdraw any tokens from the contract at any time.
  • Any Operator can grant or revoke the Operator role from any address at any time.
  • The owner of this contract is intended to be the AstroFarm contract.
AstroFarm Contract:
  • This contract allows users to stake various tokens into pools to earn rewards over time in the form of AstroTokens.
  • When staking, user are minted an equal amount of AstroStake tokens.
  • Users receive rewards per block based on the token stake time, multiplier bonus, and points allocated to the pool.
  • Users may withdraw their staked funds at any time; rewards are then automatically claimed. An equal amount of the user's AstroStake tokens are burned.
  • Rewards will stop being generated after an "end time" has passed.
  • The owner can update the end time to any value at any time.
  • The owner can add a new pool or update a pool's share of rewards at any time.
  • The owner can update the rate of rewards generated at any time.
  • The owner can update the bonus multiplier to any value at any time, including 0.
  • A Migrator function is present, allowing the team to update a pool's token to a new token without restriction. This would result in pool withdraws to be in the form of the new token.
  • The user can also trigger an emergency withdraw, which will transfer all of the user's deposited tokens for a specified pool to their wallet address without calculating rewards.
  • The AstroFarm staking contract should not be used with fee-on-transfer or ERC-777 tokens. If a fee-on-transfer token is added as a staking asset, then the contract must be exempt from transfer fees.
  • The team must also be careful not to add the same token twice for staking.

External Threat Results

Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Centralization of Control
  • The team retains ownership controls outlined above.
  • The owner of the AstroFarm contract can update a pool's token to a different token at any time.
  • 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
    Integer Over/UnderflowN/APASS
    Logical IssuesDelegates are not moved appropriately in the governance token contracts.FAIL
    Multiple SendsN/APASS
    SuicideN/APASS
    State Change External CallsN/APass
    Unchecked RetvalN/APASS
    User Supplied AssertionN/APASS
    Critical Solidity CompilerN/APASS
    Overall Contract Safety FAIL

    Function Graph

    ERC20 Token Graph


    Inheritence Chart

    Multi-file Token


    Functions Overview

    
    							
    
     ($) = payable function
     # = non-constant function
     				
      + [Lib] SafeMath 
        - [Int] add
        - [Int] sub
        - [Int] sub
        - [Int] mul
        - [Int] div
        - [Int] div
        - [Int] mod
        - [Int] mod
        - [Int] min
        - [Int] sqrt
    
     + [Int] IBEP20 
        - [Ext] totalSupply
        - [Ext] decimals
        - [Ext] symbol
        - [Ext] name
        - [Ext] getOwner
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
    
     + [Lib] Address 
        - [Int] isContract
        - [Int] sendValue #
        - [Int] functionCall #
        - [Int] functionCall #
        - [Int] functionCallWithValue #
        - [Int] functionCallWithValue #
        - [Prv] _functionCallWithValue #
    
     + [Lib] SafeBEP20 
        - [Int] safeTransfer #
        - [Int] safeTransferFrom #
        - [Int] safeApprove #
        - [Int] safeIncreaseAllowance #
        - [Int] safeDecreaseAllowance #
        - [Prv] _callOptionalReturn #
    
     +  Context 
        - [Pub]  #
        - [Int] _msgSender
        - [Int] _msgData
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
        - [Int] _transferOwnership #
    
     +  BEP20 (Context, IBEP20, Ownable)
        - [Pub]  #
        - [Ext] getOwner
        - [Pub] name
        - [Pub] decimals
        - [Pub] symbol
        - [Pub] totalSupply
        - [Pub] balanceOf
        - [Pub] transfer #
        - [Pub] allowance
        - [Pub] approve #
        - [Pub] transferFrom #
        - [Pub] increaseAllowance #
        - [Pub] decreaseAllowance #
        - [Pub] mint #
           - modifiers: onlyOwner
        - [Int] _transfer #
        - [Int] _mint #
        - [Int] _burn #
        - [Int] _approve #
        - [Int] _burnFrom #
    
     +  AstroToken (BEP20)
        - [Pub] burn #
        - [Pub] mint #
           - modifiers: onlyOwner
        - [Ext] delegates
        - [Ext] delegate #
        - [Ext] delegateBySig #
        - [Ext] getCurrentVotes
        - [Ext] getPriorVotes
        - [Int] _delegate #
        - [Int] _moveDelegates #
        - [Int] _writeCheckpoint #
        - [Int] safe32
        - [Int] getChainId
    
     +  AstroStake (BEP20)
        - [Pub] mint #
           - modifiers: onlyOwner
        - [Pub] burn #
           - modifiers: onlyOwner
        - [Pub]  #
        - [Pub] safeCakeTransfer #
           - modifiers: onlyOwner
        - [Ext] withdrawAnyToken #
        - [Ext] setOperator #
        - [Ext] delegates
        - [Ext] delegate #
        - [Ext] delegateBySig #
        - [Ext] getCurrentVotes
        - [Ext] getPriorVotes
        - [Int] _delegate #
        - [Int] _moveDelegates #
        - [Int] _writeCheckpoint #
        - [Int] safe32
        - [Int] getChainId
    
     + [Int] IMigratorChef 
        - [Ext] migrate #
    
     +  AstroFarm (Ownable)
        - [Pub]  #
        - [Pub] updateMultiplier #
           - modifiers: onlyOwner
        - [Ext] poolLength
        - [Pub] add #
           - modifiers: onlyOwner
        - [Pub] set #
           - modifiers: onlyOwner
        - [Int] updateStakingPool #
        - [Ext] updateStakingPoolAlloc #
           - modifiers: onlyOwner
        - [Ext] updateCakePerSecond #
           - modifiers: onlyOwner
        - [Ext] updateEndTimestamp #
           - modifiers: onlyOwner
        - [Pub] setMigrator #
           - modifiers: onlyOwner
        - [Pub] migrate #
        - [Pub] getMultiplier
        - [Ext] pendingCake
        - [Pub] massUpdatePools #
        - [Pub] updatePool #
        - [Pub] deposit #
        - [Pub] withdraw #
        - [Pub] enterStaking #
        - [Pub] leaveStaking #
        - [Pub] emergencyWithdraw #
        - [Int] safeCakeTransfer #
        - [Pub] dev #