SuperLauncher Token & Presale Platform - Smart Contract Audit Report
Summary
SuperLauncher is building a launchpad for projects on the Binance Smart Chain to launch in a safe, trusted, and decentralized manner.
For this audit, we reviewed SuperLauncher's contracts at commit 51e9ed805132f1f335c826a43a626197d1cd4af2 on GitHub.Notes on the Token Contract:The initial supply of the token is 4 million with 2 million locked tokens. The locked tokens will be released to the team as follows: 50k any time, 500k after 30 days, 700k after 150 days, 750k after 270 days. At the time of deployment all initial tokens are delivered to the deployer's address. The team is able to mint tokens after deployment up to a cap of 12 million. A small amount of gas can be saved via marking functions external instead of public. The contract utilizes SafeMath to prevent overflow issues. The owner of the contract (with minting powers) has been set to a 3/4 multisig wallet controlled by the team.
Notes on the Factory & Presale Campaign Contracts:The Factory contract exists to deploy Presale Campaign contracts. The SuperLauncher team can call the createCampaign() function to generate a presale, passing in variables around the presale duration, cost, liquidity lock time & percentage, etc. The caller can elect to have unsold tokens burned or returned to them. Teams setting up presales can set the presale to be public or only for whitelisted addresses. Additionally, teams can also set a mid-sale date, where only whitelisted participants will be able to participate in the first portion, and everyone can participate in the second portion. In order to participate in a presale, users must have at least an amount of SuperLauncher tokens as defined by the team setting up the presale. This value can be 0 if the team setting up the presale so chooses. While the sale is active, users can deposit BNB to purchase tokens in a presale. Tokens purchased in presales are claimable buy the buyer after the sale. After liquidity has been added, the presale team can withdraw the BNB raised as well as leftover unsold tokens. The length of a liquidity lock is set by the team running the presale. The SuperLauncher team retains the power to cancel any presale campaign at any time. The SuperLuancher team can also send all of a presale's BNB and Tokens to the campaign's owner. This is provided in case LP creation fails due to a unique token being sold. The team running the presale can also end the sale early if they choose or the hardcap is met. In case a presale fails or is not successful, users can withdraw their contributed BNB. At the conclusion of the sale, the SuperLauncher team (via the FeeVault contract) will receive a fee in BNB for hosting the presale. The FeeVault contract splits BNB received as fees among two addresses controlled by the team. The contracts utilize SafeMath to prevent overflow issues. Proper structuring of logic around BNB transfers to prevent reentrancy issues. Public functions may be declared external to save a small amount of gas on each transaction.
Audit Findings Summary:
- No security issues from outside attackers were identified.
- As with any presale, ensure trust in the team prior to investing.
- Further, ensure trust in the team as they have notable power in the presale ecosystem and the ability to mint tokens.
- KYC: No.
- Date: April 6th, 2021.
- Update Date: April 12th, 2021 - Commits with slight logic changes to accomodate possible issues around creating the LP.
External Threats
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 |
Integer Over/Underflow | N/A | PASS |
Multiple Sends | 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 |
Details - SuperLauncher Token Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Int] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Lib] SafeMath
- [Int] tryAdd
- [Int] trySub
- [Int] tryMul
- [Int] tryDiv
- [Int] tryMod
- [Int] add
- [Int] sub
- [Int] mul
- [Int] div
- [Int] mod
- [Int] sub
- [Int] div
- [Int] mod
+ ERC20 (Context, IERC20)
- [Pub] #
- [Pub] name
- [Pub] symbol
- [Pub] decimals
- [Pub] totalSupply
- [Pub] balanceOf
- [Pub] transfer #
- [Pub] allowance
- [Pub] approve #
- [Pub] transferFrom #
- [Pub] increaseAllowance #
- [Pub] decreaseAllowance #
- [Int] _transfer #
- [Int] _mint #
- [Int] _burn #
- [Int] _approve #
- [Int] _setupDecimals #
- [Int] _beforeTokenTransfer #
+ ERC20Burnable (Context, ERC20)
- [Pub] burn #
- [Pub] burnFrom #
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Int] functionStaticCall
- [Int] functionStaticCall
- [Int] functionDelegateCall #
- [Int] functionDelegateCall #
- [Prv] _verifyCallResult
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ SuperLauncherToken (ERC20, ERC20Burnable, Ownable)
- [Pub] #
- modifiers: ERC20
- [Pub] mint #
- modifiers: onlyOwner
- [Pub] unlockTeamAllocation #
- modifiers: onlyOwner
- [Pub] getTeamAllocationUnlockDate
Details - Presale Factory
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Int] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ [Lib] SafeMath
- [Int] tryAdd
- [Int] trySub
- [Int] tryMul
- [Int] tryDiv
- [Int] tryMod
- [Int] add
- [Int] sub
- [Int] mul
- [Int] div
- [Int] mod
- [Int] sub
- [Int] div
- [Int] mod
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ ERC20 (Context, IERC20)
- [Pub] #
- [Pub] name
- [Pub] symbol
- [Pub] decimals
- [Pub] totalSupply
- [Pub] balanceOf
- [Pub] transfer #
- [Pub] allowance
- [Pub] approve #
- [Pub] transferFrom #
- [Pub] increaseAllowance #
- [Pub] decreaseAllowance #
- [Int] _transfer #
- [Int] _mint #
- [Int] _burn #
- [Int] _approve #
- [Int] _setupDecimals #
- [Int] _beforeTokenTransfer #
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Int] functionStaticCall
- [Int] functionStaticCall
- [Int] functionDelegateCall #
- [Int] functionDelegateCall #
- [Prv] _verifyCallResult
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ [Int] IFactoryGetters
- [Ext] getLpRouter
- [Ext] getFeeAddress
- [Ext] getLauncherToken
+ [Int] IUniswapV2Router02
- [Ext] addLiquidityETH ($)
+ Campaign
- [Pub] #
- [Ext] initialize #
- [Ext] fundIn #
- modifiers: onlyCampaignOwner
- [Ext] fundOut #
- modifiers: onlyCampaignOwner
- [Pub] buyTokens ($)
- [Pub] finishUp #
- [Pub] withdrawLP #
- modifiers: onlyCampaignOwner
- [Pub] refund #
- [Pub] getReturnTokenAmt
- [Pub] appendWhitelisted #
- modifiers: onlyCampaignOwner
- [Pub] removeWhitelisted #
- modifiers: onlyCampaignOwner
- [Pub] checkWhiteList
- [Int] sendAllTokensTo #
- [Int] getFeeAmt
- [Int] getFeeAddress
- [Pub] failedOrCancelled
- [Pub] isLive
- [Pub] calculateTokenAmount
- [Pub] getRemaining
- [Pub] setCancelled #
- modifiers: onlyFactory
- [Pub] getCampaignFundInTokensRequired
- [Pub] checkQualifyingTokens
+ Factory (IFactoryGetters, Ownable)
- [Pub] #
- modifiers: Ownable
- [Pub] createCampaign #
- modifiers: onlyOwner
- [Ext] cancelCampaign #
- modifiers: onlyOwner
- [Ext] getLpRouter
- [Ext] getFeeAddress
- [Ext] getLauncherToken
Details - Presale Campaign
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ Context
- [Int] _msgSender
- [Int] _msgData
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Lib] SafeMath
- [Int] tryAdd
- [Int] trySub
- [Int] tryMul
- [Int] tryDiv
- [Int] tryMod
- [Int] add
- [Int] sub
- [Int] mul
- [Int] div
- [Int] mod
- [Int] sub
- [Int] div
- [Int] mod
+ ERC20 (Context, IERC20)
- [Pub] #
- [Pub] name
- [Pub] symbol
- [Pub] decimals
- [Pub] totalSupply
- [Pub] balanceOf
- [Pub] transfer #
- [Pub] allowance
- [Pub] approve #
- [Pub] transferFrom #
- [Pub] increaseAllowance #
- [Pub] decreaseAllowance #
- [Int] _transfer #
- [Int] _mint #
- [Int] _burn #
- [Int] _approve #
- [Int] _setupDecimals #
- [Int] _beforeTokenTransfer #
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Int] functionStaticCall
- [Int] functionStaticCall
- [Int] functionDelegateCall #
- [Int] functionDelegateCall #
- [Prv] _verifyCallResult
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ [Int] IFactoryGetters
- [Ext] getLpRouter
- [Ext] getFeeAddress
- [Ext] getLauncherToken
+ [Int] IUniswapV2Router02
- [Ext] addLiquidityETH ($)
+ Campaign
- [Pub] #
- [Ext] initialize #
- [Ext] fundIn #
- modifiers: onlyCampaignOwner
- [Ext] fundOut #
- modifiers: onlyCampaignOwner
- [Pub] buyTokens ($)
- [Pub] finishUp #
- [Pub] withdrawLP #
- modifiers: onlyCampaignOwner
- [Pub] refund #
- [Pub] getReturnTokenAmt
- [Pub] appendWhitelisted #
- modifiers: onlyCampaignOwner
- [Pub] removeWhitelisted #
- modifiers: onlyCampaignOwner
- [Pub] checkWhiteList
- [Int] sendAllTokensTo #
- [Int] getFeeAmt
- [Int] getFeeAddress
- [Pub] failedOrCancelled
- [Pub] isLive
- [Pub] calculateTokenAmount
- [Pub] getRemaining
- [Pub] setCancelled #
- modifiers: onlyFactory
- [Pub] getCampaignFundInTokensRequired
- [Pub] checkQualifyingTokens
Details - FeeVault
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ [Lib] SafeMath
- [Int] tryAdd
- [Int] trySub
- [Int] tryMul
- [Int] tryDiv
- [Int] tryMod
- [Int] add
- [Int] sub
- [Int] mul
- [Int] div
- [Int] mod
- [Int] sub
- [Int] div
- [Int] mod
+ FeeVault
- [Pub] #
- [Ext] ($)