SafeLaunch - Smart Contract Audit Report
SafeLaunch is building a new yield-farming and staking platform where users can earn rewards in SFEX tokens.
Notes on the Contract:
Audit Findings Summary
- 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.
- 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
|Arbitrary Storage Write||N/A||PASS|
|Delegate Call to Untrusted Contract||N/A||PASS|
|Dependence on Predictable Variables||N/A||PASS|
|State Change External Calls||N/A||PASS|
|User Supplied Assertion||N/A||PASS|
|Critical Solidity Compiler||N/A||PASS|
|Overall Contract Safety||PASS|
($) = 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 #