Safe Whale - Smart Contract Audit Report

Summary

Safe Whale Audit Report Safe Whale is a new yield farming platform allowing users to create new BEP20 and BEP721 based farms.

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

Notes on Individual Contracts:
Notes on the FarmFactory Contract:
  • Any user who pays the fee can use the FarmFactory contract to create a new BEP20Farm or BEP721Farm; the user is set as the owner in the newly created Farm.
  • The implementation code for the BEP20Farm or BEP721Farm 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. There is no max value for the cooldown period.
Notes on the BEP20Farm and BEP721Farm 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 BEP777-compliant tokens (this is uncommon).
  • Users will receive a reward amount 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 once a day.
  • A cooldown period must pass before users are able to unstake their assets.
  • Fees are taken on deposit and withdrawal in the BEP20 Farm contract; they are taken from rewards payouts in the BEP721 Farm contract. There is no limit on fees taken and they can be set up to 100%.
  • On withdrawals, the user will receive the entire amount of the staking tokens they deposited minus fees where applicable; 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 permanently distribute 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 will disable all regular functionality of the contract.
  • While in an emergency state, the owner is able 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.
General Notes on all Contracts:
  • The contracts comply with the relevant BEP721 and BEP20 token standards.
  • As the project is implemented with Solidity version ^0.8.4, it is protected from overflows.
  • The team worked with us to implement changes related to gas optimization.
Audit Findings Summary
  • No external threats were identified.
  • Ensure trust in the team as they have considerable control within the ecosystem.
  • Date: November 4th, 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

SafeWhale Graph

SafeWhale


 ($) = 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] Constructor #
    - [Pub] owner
    - [Pub] renounceOwnership #
       - modifiers: onlyOwner
    - [Pub] transferOwnership #
       - modifiers: onlyOwner

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

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

 +  FarmFactory (Ownable)
    - [Pub] Constructor #
    - [Ext] Fallback ($)
    - [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