Safe Whale - Smart Contract Audit Report
Summary
Safe Whale is a new yield farming platform allowing users to create new BEP20 and BEP721 based farms.
Notes on Individual Contracts:
Notes on the FarmFactory Contract:Notes on the BEP20Farm and BEP721Farm Contracts:
- 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.
General Notes on all 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.
Audit Findings Summary
- 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.
- 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 Category | Notes | Result |
---|---|---|
Arbitrary Storage Write | N/A | PASS |
Arbitrary Jump | N/A | PASS |
Delegate Call to Untrusted Contract | N/A | PASS |
Dependence on Predictable Variables | N/A | PASS |
Deprecated Opcodes | N/A | PASS |
Ether Thief | N/A | PASS |
Exceptions | N/A | PASS |
External Calls | N/A | PASS |
Flash Loans | N/A | PASS |
Integer Over/Underflow | N/A | PASS |
Multiple Sends | N/A | PASS |
Oracles | N/A | PASS |
Suicide | N/A | PASS |
State Change External Calls | N/A | PASS |
Unchecked Retval | N/A | PASS |
User Supplied Assertion | N/A | PASS |
Critical Solidity Compiler | N/A | PASS |
Overall Contract Safety | PASS |
($) = 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