SafeLaunch - Smart Contract Audit Report


Sanshu Inu Audit Report SafeLaunch is building a new yield-farming and staking platform where users can earn rewards in SFEX tokens.

For this audit, we reviewed SafeLaunch's MissionControl contract at commit 391e00afc6303afe2314d4a58d2d1b94388bc8af on the team's private GitHub.

Notes on the Contract:
  • Rewards are calculated based on a portion of the user's staked amount proportional to the allocation percentage assigned to the pool multiplied by the seconds since their last claim time; staking rewards may be minimized to the available SFEX balance in the contract if there are not enough SFEX tokens at the time of calculation.
  • Staking rewards can be calculated and claimed by the user at any time.
  • Reward distribution may fail if there are not enough SFEX tokens in the contract balance.
  • On deposits, all the user's funds for that pool are locked for the lock time specified for the pool and will not be able to be withdrawn until the lock time has elapsed.
  • On withdrawals, the user will receive the desired amount of LP tokens; this amount cannot be more than the amount the user has deposited.
  • The user can also trigger an emergency withdraw, which will transfer a portion of the user's deposited LP tokens to the fee collector wallet, and the remaining part to a wallet address specified by the user, ignoring any rewards that may have accrued.
  • On deposits, withdrawals, and reward claims, as long as the SFEX Rewarder contract is set, the onSfexRewards() function will be called; we advise proceeding with caution when using this contract, as the logic for this function has not been provided and was unable to be verified by our team.
  • The contract includes a migrate() function to migrate LP tokens to another LP contract using an external migrator contract. As the owner can set the migrator address to any address at any time, the owner can use this function to grant approvals to a malicious contract which can be used to drain all the user's staked funds.

  • The owner can use the MissionControl contract to add pools for LP tokens; the team must exercise caution when adding tokens to avoid fee-on-transfer and ERC777-compliant tokens (this is uncommon).
  • Tokens with deflationary mechanisms should not be added to the staking platform; or, the staking contract should be excluded from the token's fee mechanism.
  • The owner is able to add any token address as an LP pool, and may add multiple pools with the same token address; the team must be careful not to add the same pool twice or implement a check to prevent this.
  • The owner can set the allocation points, rewarder address, and the lock time for any existing pool at any time.
  • The owner can set the rewards rate to any value at any time.
  • The owner can set the migrator address to any address at any time.
  • The owner can set the fee collector address only once on construction.
  • The fee collector can set the fee percentage to any value up to 100% at any time.

  • Some functions could have been declared external for gas optimization.
Audit Findings Summary
  • No security issues from outside attackers were identified.
  • Ensure trust in the team as they have substantial control in the ecosystem via their ability to set fees to any value and migrate user's staked funds.
  • Date: July 21st, 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
External CallsN/APASS
Flash LoansN/APASS
Integer Over/UnderflowN/APASS
Multiple SendsN/APASS
State Change External CallsN/APASS
Unchecked RetvalN/APASS
User Supplied AssertionN/APASS
Critical Solidity CompilerN/APASS
Overall Contract Safety PASS

ERC20 Token Graph

Contract Inheritance

 ($) = payable function
 # = non-constant function
 + [Lib] BoringMath 
    - [Int] add
    - [Int] sub
    - [Int] mul
    - [Int] to128
    - [Int] to64
    - [Int] to32

 + [Lib] BoringMath128 
    - [Int] add
    - [Int] sub

 + [Lib] BoringMath64 
    - [Int] add
    - [Int] sub

 + [Lib] BoringMath32 
    - [Int] add
    - [Int] sub

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

 + [Lib] BoringERC20 
    - [Int] safeSymbol
    - [Int] safeName
    - [Int] safeDecimals
    - [Int] safeTransfer #
    - [Int] safeTransferFrom #

 +  BaseBoringBatchable 
    - [Int] _getRevertMsg
    - [Ext] batch ($)

 +  BoringBatchable (BaseBoringBatchable)
    - [Pub] permitToken #

 +  BoringOwnableData 

 +  BoringOwnable (BoringOwnableData)
    - [Pub]  #
    - [Pub] transferOwnership #
       - modifiers: onlyOwner
    - [Pub] claimOwnership #

 + [Lib] SignedSafeMath 
    - [Int] mul
    - [Int] div
    - [Int] sub
    - [Int] add
    - [Int] toUInt256

 + [Int] ISfexRewarder 
    - [Ext] onSfexReward #
    - [Ext] pendingTokens

 + [Int] IMigratorChef 
    - [Ext] migrate #

 +  MissionControl (BoringOwnable, BoringBatchable)
    - [Pub]  #
    - [Pub] poolLength
    - [Pub] addWithLock #
       - modifiers: onlyOwner
    - [Prv] _getLpSupply
    - [Prv] _getSfexRewardForTime
    - [Prv] _trackPendingSfexReward #
    - [Pub] add #
       - modifiers: onlyOwner
    - [Pub] set #
       - modifiers: onlyOwner
    - [Pub] setSfexPerSecond #
       - modifiers: onlyOwner
    - [Pub] setMigrator #
       - modifiers: onlyOwner
    - [Pub] migrate #
    - [Ext] pendingSfex
    - [Ext] massUpdatePools #
    - [Pub] updatePool #
    - [Prv] _depositLpToken #
    - [Prv] _withdrawLpToken #
    - [Pub] deposit #
    - [Prv] _paySfexReward #
    - [Pub] withdraw #
    - [Pub] harvest #
    - [Pub] withdrawAndHarvest #
    - [Pub] emergencyWithdraw #
    - [Pub] setFeeCollector #
    - [Pub] setFeePercent #