Safe Farm - Smart Contract Audit Report

Summary

Safe Farm Audit Report Safe Farm is a new yield farm platform allowing users to create ERC20 and ERC721 based farms.

For this audit, we reviewed the FarmFactory, ERC20Farm, and ERC721Farm contracts provided to us by the team.

Notes on the ERC20Farm and ERC721Farm Contracts::
  • These contracts allow users to stake a single asset determined by the project team in exchange for rewards in a second asset determined by the team.
  • In order to stake users must have a minimum amount of a tertiary "utility" asset. Both the asset and the minimum amount needed are determined by the team.
  • The team must exercise caution when deciding the staking token to avoid ERC777-compliant tokens (this is uncommon).
  • Users will receive a reward amount for every 15 minute period based on the amount staked and the reward rate set by the owner on deployment; staking rewards can be calculated and transferred to the user at any time.
  • A cooldown period must pass before users are able to unstake their token. There is no max value for the cooldown period.
  • Fees are taken on deposit and withdrawal in the ERC20 Farm contract; they are taken from rewards payouts in the ERC721 Farm contract. There is no limit on fees taken and can be up to 100%.
  • On withdrawals, the user will receive the entire amount of the staking tokens they deposited minus fees; pending rewards are calculated and transferred.
  • Users also have the option to collect their rewards without unstaking.
  • Fees are initially collected in the contract for the owner to withdraw. The owner may elect to stop receiving fees and instead begin permanently distributing them as rewards amongst stakers.
  • Reward tokens must be supplied to the contract to be distributed. Users will lose their rewards if they withdraw while there are no reward tokens in the contract.
  • The owner is able to put the contract into an emergency state at anytime. This allows the owner to withdraw all of the rewards tokens in the contract. Users can also trigger an emergency withdraw, which will transfer all the user's deposited tokens to their wallet address, without calculating rewards.
Notes on the FarmFactory Contract:
  • Any user who pays the fee can use the FarmFactory contract to create a new ERC20Farm or ERC721Farm; the user is set as the owner in the newly created Farm.
  • The implementation code for the ERC20Farm or ERC721Farm is set by the project team.
  • The owner is able to withdraw the collected fees from this contract at anytime.
  • The owner is able to set the fee to any amount at anytime.
  • The owner is able to set the cooldown period before users can unstake in any of the farms at anytime.
  • The contract is ERC721 compliant; all standard functionality is present.
  • As the project is implemented with solidity version ^0.8.0, it is protected from overflows.
Audit Findings Summary
  • No external threats were identified.
  • Ensure trust in the team as they have considerable control within the ecosystem.
  • Date: November 1st, 2021.

Audit 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
Flash LoansN/APASS
Integer Over/UnderflowN/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

SafeFarm Graph

SafeFarm


 ($) = payable function
 # = non-constant function

+ [Int] IERC20 
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #

+ [Int] IERC165 
- [Ext] supportsInterface

+ [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 #

+  Context 
- [Int] _msgSender
- [Int] _msgData

+  Ownable (Context)
- [Pub]  #
- [Pub] owner
- [Pub] renounceOwnership #
   - modifiers: onlyOwner
- [Pub] transferOwnership #
   - modifiers: onlyOwner

+  ERC20Farm (Context)
- [Pub]  #
- [Ext] stake #
- [Ext] unstake #
- [Ext] seed ($)
- [Ext] withdraw #
- [Ext] emergencySwitch #
- [Ext] emergencyWithdraw #
- [Ext] emergencyUnstake #
- [Ext] routeFeesBackToFarm #
- [Ext] setCooldown #
- [Ext] getFees
- [Ext] getUtilityToken
- [Ext] getUtilityRequirement
- [Ext] getStakedToken
- [Ext] getRewardToken
- [Ext] getFee
- [Ext] getCooldown
- [Ext] getRewardRate
- [Pub] getRewardRateTokens
- [Ext] getRewardAPY
- [Ext] getRewardsTotal
- [Pub] payout #
- [Pub] payoutFlex #
- [Pub] getStakedTotal
- [Pub] getUserStartedStaking
- [Pub] getUserStaked
- [Pub] getUserFarmed
- [Pub] getUserFeeOfAmount
- [Pub] getUserRewardsAvailable
- [Pub] getUserEstimatedRewardDaily

+  ERC721Farm (IERC721Receiver, Context)
- [Pub]  #
- [Ext] stake #
- [Ext] unstake #
- [Ext] seed ($)
- [Ext] withdraw #
- [Ext] emergencySwitch #
- [Ext] emergencyWithdraw #
- [Ext] emergencyUnstake #
- [Ext] routeFeesBackToFarm #
- [Ext] setCooldown #
- [Ext] getFees
- [Ext] getUtilityToken
- [Ext] getUtilityRequirement
- [Ext] getStakedToken
- [Ext] getRewardToken
- [Ext] getFee
- [Ext] getCooldown
- [Ext] getPlatform
- [Pub] getRewardRate
- [Ext] getRewardAPY
- [Ext] getRewardsTotal
- [Pub] payout #
- [Pub] payoutFlex #
- [Pub] getStakedTotal
- [Pub] getUserStartedStaking
- [Pub] getUserStaked
- [Pub] getUserStakedIDs
- [Pub] getUserRewards
- [Pub] getUserFeeOfAmount
- [Pub] getUserRewardsAvailable
- [Pub] getUserEstimatedRewardDaily
- [Pub] onERC721Received #

+  FarmFactory (Ownable)
- [Pub]  #
- [Ext]  ($)
- [Ext] createERC20Farm ($)
- [Ext] createERC721Farm ($)
- [Ext] withdraw #
   - modifiers: onlyOwner
- [Ext] setFee #
   - modifiers: onlyOwner
- [Ext] setCooldownFarm #
   - modifiers: onlyOwner
- [Ext] getFee
- [Ext] getERC20Farms
- [Ext] getERC721Farms
- [Ext] getERC20FarmsLength
- [Ext] getERC721StakingPoolsLength