MoonFORCE

Smart Contract Audit Report

Audit Summary

MoonFORCE is a new ERC-20 token with fees on certain buys and sells.

For this audit, we reviewed the project team's MoonFORCE and MoonshotMechanism contracts at 0x6149367D714cc9143a9cA9EdA965F343fe009388 on the Binance Smart Chain Testnet.

Audit Findings

Please ensure trust in the team prior to investing as they have some control in the ecosystem.
Date: April 12th, 2022.
Updated: April 12th, 2022 to reflect changes from address 0x76D8Ae082123b6A3fE37563b5AaD7f7229561221 on the Binance Smart Chain Mainnet to address 0x2a954911C64aa95e7D3D8261CDF0B2efC2CCE0B8 on the Testnet.
Updated: April 14th, 2022 to reflect changes from address 0x2a954911C64aa95e7D3D8261CDF0B2efC2CCE0B8 to address 0x32326DC9405A0986D2f92e2908A026395135ea50.
Updated: April 15th to reflect changes from address 0x32326DC9405A0986D2f92e2908A026395135ea50 to address 0x6149367D714cc9143a9cA9EdA965F343fe009388.

Finding #1 - MoonFORCE - High (Resolved)

Description: If a user transfers or receives tokens from a non-Staking Contract, their share balance will be updated to their current balance, ignoring their staked balance.
Risk/Impact: A user's share balance is intended to be the sum of their token balance and their staked tokens; however, their share balance will be less than this if they send or receive tokens while having tokens staked. Users will have to fully unstake in order to fix their share balance.
Recommendation: The team should change the logic so that staked shares are tracked in a separate variable.
Resolution: The team has implemented the above recommendation. A user's "Owned Balance" is now calculated as the sum of their separately tracked "staked" amount and their token balance.

Finding #2 - MoonFORCE - High (Resolved)

Description: If a user partially unstakes from one of the contract's Staking Contracts, their shares will be deducted by the amount remaining in the staking contract.
Risk/Impact: A user's share balance is intended to be the sum of their token balance and their staked tokens; however, their share balance will be less than this if they partially unstake. Users will have to fully unstake in order to fix their share balance.
Recommendation: The team should change the logic so that staked shares are tracked in a separate variable.
Resolution: The team has implemented the above recommendation.

Finding #3 - MoonshotMechanism - High (Resolved)

Description: Buybacks can be triggered by any user and in large amounts.
Risk/Impact: Predictable buybacks and buybacks in large amounts can lead to price manipulation.
Recommendation: The team should lower the buyback amount and only allow authorized users to trigger buybacks.
Resolution: The team has limited the buyback amount to .1BNB. The team should exercise caution and not add Moonshots with values over 10,000, which could result in an increased buyback amount.

Finding #4 - MoonFORCE - Low (Resolved)

Description: No event is emitted on transfers from sell fees.
Risk/Impact: If any fees are updated, the sell fees will no longer be 0, meaning an event should be emitted to account for fees taken or else the MoonFORCE tokenomics will become increasingly skewed on blockchain explorers over time.
Recommendation: Lines 2881-2883 should be updated to the following so that events are properly emitted when sell fees are taken:
if(takeFee == 0) {
	restoreAllFee();
} else {
	restoreAllFee();
	emit Transfer(sender, MoonshotAddress, _values.reflection.add(_values.Moonshots));
	emit Transfer(sender, _defaultFees.MarketingAddress, _values.Marketing);
	emit Transfer(sender, _burnAddress, _values.buyBack);
Resolution: The team has removed sell fees when selling to a contract in the Pair list, so additional events are no longer needed for this case.

Finding #5 - MoonFORCE & MoonshotMechanism - Informational (Resolved)

Description: The following variables are not declared constant, but cannot be updated:
_burnAddress, _tTotal.
Recommendation: The team has declared these variables constant.

Finding #6 - MoonFORCE & MoonshotMechanism - Informational (Resolved)

Description: The following variables are declared, but are never used:
launchedAt, launchedAtTimestamp, swapEnabled.
Recommendation: These variables can be removed for gas saving purposes.
Resolution: The team has removed these variables.

Contracts Overview

  • As the contracts are implemented with SafeMath, they are safe from any possible overflows/underflows.
MoonFORCE Contract:
  • Upon deployment, the owner is transferred the total supply of 10 billion tokens.
  • No public minting or burning functions are present; however, users can transfer their tokens to the 0x..dead address to reduce circulating supply, if desired.
  • Users cannot sell or transfer more than the maximum transaction amount at once unless they have been excluded from the transaction limit.
  • If the MoonshotMechanism contract's WBNB balance is greater than its "disbursal threshold", the disbursal threshold is not 0, and automatic Moonshots are enabled, the MoonshotMechanism contract's launchMoonshot() function will be called on any token sell to any contract in the Pair list.
  • Whe selling to a contract in the Pair list, users will pay no fee.
  • When selling to a contract in the "Outside" Pair list, users will pay a Reflection fee, Liquify fee, Moonshot fee, Marketing fee, and Burn fee.
  • When buying from a contract in the Outside Pair list, users will also pay a Reflection fee, Liquify fee, Moonshot fee, Marketing fee, and Burn fee.
  • If buying or selling from a contract in the Pair list, users will not pay any fees.
  • Fee-excluded users will not pay any fees when buying or selling to Outside Pairs.
  • Any Reflection and Moonshot fees are sent to the Moonshot address.
  • Any Marketing, Liquify, and Burn fees are sent to the Marketing, and, Liquify, and 0x..dead addresses, respectively.
  • A user's "Owned Balance" is equal to the sum of their "staked" amount and their token balance.
  • When transferring to or from a contract marked as a Staking Contract, users staked balances are incremented or decremented accordingly, meaning their Owned Balance will not be affected.
  • Any contract in the Pair list and the PYESwapRouter address can call the depositLPFee() function at any time, which will transfer a specified token from the caller to this contract and swap it for WBNB (if it not already WBNB).
  • A Marketing fee, Reflection fee, Moonshot fee, Liquify fee, and Buyback fee are all taken from the resulting BNB.
  • The Marketing, Moonshot, and Liquify fees are then sent to their appropriate addresses.
  • The Buyback fee is stored in this contract until the next buyback occurs unless withdrawn by the owner.
  • If a Staking Contract has been set, the reflection fee is transferred to it, then its depositWBNBToStakingContract() function is called, passing in the reflection fee amount.
  • If the Staking Contract is not set, the reflection fee is transferred to the Liquify address.
  • As the PYESwapPair, PYESwapRouter, and Staking contracts were not included in the scope of this audit, we cannot provide an assessment with regards to security or functionality.
  • If buybacks are enabled, they will occur on a transfer once the contract has reached a certain threshold of WBNB, a certain number of blocks have passed since the last buyback, and the transfer amount is greater than a specified "minimum trigger amount".
  • Buybacks will stop occurring if the total buyback amount has exceeded a specified "Buyback Cap".
  • The resulting tokens are sent to the 0x..dead address.
  • The project team should ensure that buybacks occur in small amounts to reduce the risk of frontrunning; the team can also monitor buybacks and reduce the threshold if any unusual activity is detected.
  • The Admin Role can toggle buybacks or update the buyback threshold, minimum buyback period, minimum trigger amount, and Buyback Cap at any time.
  • The owner can update the Marketing address, Liquify address, Moonshot address, and Default Staking Contract address at any time.
  • The owner can add or remove any address from the list of Staking Contracts at any time.
  • The owner can include or exclude any address from sell fees to contracts in the Pair list at any time.
  • The owner can include or exclude any address from the maximum transaction limit at any time.
  • The Admin Role can update the Default Pair and Router addresses at any time.
  • The owner can add or remove a Pair from the Pair list or Outside Pair list at any time.
  • The owner can update the Reflection fee, Liquify fee, Moonshot fee, Marketing fee, and Burn fee to any percentages at any time.
  • The owner can withdraw any BNB or tokens, including MoonFORCE tokens, from the contract at any time.
MoonshotMechanism Contract:
  • This contract is used to collect MoonFORCE tokens and WBNB, which are then used to perform buybacks and deposit funds into a specified Staking contract.
  • Any user can call the launchMoonshot() function if the contract's WBNB balance is greater than the "disbursal threshold" and the disbursal threshold is not 0.
  • An amount of BNB equal to the disbursal threshold is then used to purchase MoonFORCE tokens; these tokens are then transferred to a Staking contract, and the Staking Contract's depositMFToStakingContract() function is called.
  • A "Moonshot" is then pseudorandomly chosen from the Moonshot list using a hash of block.timestamp and block.difficulty, and the disbursal threshold is updated to the chosen Moonshot's value multiplied by 10^13.
  • The team should exercise caution when setting Moonshot values as to avoid setting the buyback threshold to a large amount.
  • The Admin can update the Staking contract address at any time.
  • The Admin can add or remove a Moonshot from the Moonshot list at any time.
  • The Admin can update the disbursal threshold at any time.
  • The Admin can toggle automatic Moonshot launches at any time.
  • The Admin can update the Admin address at any time.
  • The Admin can swap any token in the contract for WBNB using the PYESwapRouter contract at any time.
  • As the Staking contracts was not included in the scope of this audit, we are unable to provide an assessment with regards to security or functionality.
  • The Admin can withdraw any BNB or tokens from the contract at any time.

Audit Results

Vulnerability CategoryNotesResult
Arbitrary Jump/Storage WriteN/APASS
Centralization of Control
  • The owner has the permissions described above.
  • The owner can disable buybacks in both contracts at any time.
  • The owner can withdraw any BNB or tokens from the contracts at any time, including MoonFORCE tokens accumulated for buybacks.
  • The owner can set the total fees to any amounts.
WARNING
Compiler IssuesN/APASS
Delegate Call to Untrusted ContractN/APASS
Dependence on Predictable VariablesThe randomness functionality used in the MoonshotMechanism contract to select a random Moonshot can be predicted; however, the likelihood of this along with its use for exploitation is extremely low.PASS
Ether/Token TheftN/APASS
Flash LoansN/APASS
Front RunningThe team can update the buyback thresholds in the MoonFORCE and MoonshotMechanism contracts to any amounts; buybacks should be limited to small amounts to reduce the risk of frontrunning.PASS
Improper EventsN/APASS
Improper Authorization SchemeN/APASS
Integer Over/UnderflowN/APASS
Logical IssuesN/APASS
Oracle IssuesN/APASS
Outdated Compiler VersionN/APASS
Race ConditionsN/APASS
ReentrancyN/APASS
Signature IssuesN/APASS
Unbounded LoopsN/APASS
Unused CodeN/APASS
Overall Contract Safety PASS

Inheritance Chart

Smart Contract Audit - Inheritance

Function Graph

Smart Contract Audit - Graph

Functions Overview


 ($) = payable function
 # = non-constant function
 
  + [Int] IStakingContract 
    - [Ext] depositWBNBToStakingContract #
    - [Ext] depositMFToStakingContract #

 + [Int] IMoonshotMechanism 
    - [Ext] getGoal
    - [Ext] getMoonshotBalance
    - [Ext] launchMoonshot #
    - [Ext] shouldLaunchMoon

 + [Int] IPYESwapRouter01 
    - [Ext] factory
    - [Ext] WETH
    - [Ext] addLiquidity #
    - [Ext] addLiquidityETH ($)
    - [Ext] removeLiquidity #
    - [Ext] removeLiquidityETH #
    - [Ext] removeLiquidityWithPermit #
    - [Ext] removeLiquidityETHWithPermit #
    - [Ext] swapExactTokensForTokens #
    - [Ext] swapTokensForExactTokens #
    - [Ext] swapExactETHForTokens ($)
    - [Ext] swapTokensForExactETH #
    - [Ext] swapExactTokensForETH #
    - [Ext] swapETHForExactTokens ($)
    - [Ext] quote
    - [Ext] getAmountOut
    - [Ext] getAmountIn
    - [Ext] getAmountsOut
    - [Ext] getAmountsIn

 + [Int] IPYESwapRouter (IPYESwapRouter01)
    - [Ext] removeLiquidityETHSupportingFeeOnTransferTokens #
    - [Ext] removeLiquidityETHWithPermitSupportingFeeOnTransferTokens #
    - [Ext] swapExactTokensForTokensSupportingFeeOnTransferTokens #
    - [Ext] swapExactETHForTokensSupportingFeeOnTransferTokens ($)
    - [Ext] swapExactTokensForETHSupportingFeeOnTransferTokens #
    - [Ext] pairFeeAddress
    - [Ext] adminFee
    - [Ext] feeAddressGet

 + [Int] IPYESwapPair 
    - [Ext] baseToken
    - [Ext] getTotalFee
    - [Ext] name
    - [Ext] symbol
    - [Ext] decimals
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] allowance
    - [Ext] updateTotalFee #
    - [Ext] approve #
    - [Ext] transfer #
    - [Ext] transferFrom #
    - [Ext] DOMAIN_SEPARATOR
    - [Ext] PERMIT_TYPEHASH
    - [Ext] nonces
    - [Ext] permit #
    - [Ext] MINIMUM_LIQUIDITY
    - [Ext] factory
    - [Ext] token0
    - [Ext] token1
    - [Ext] getReserves
    - [Ext] price0CumulativeLast
    - [Ext] price1CumulativeLast
    - [Ext] kLast
    - [Ext] mint #
    - [Ext] burn #
    - [Ext] swap #
    - [Ext] skim #
    - [Ext] sync #
    - [Ext] initialize #
    - [Ext] setBaseToken #

 + [Int] IPYESwapFactory 
    - [Ext] feeTo
    - [Ext] feeToSetter
    - [Ext] getPair
    - [Ext] allPairs
    - [Ext] allPairsLength
    - [Ext] pairExist
    - [Ext] createPair #
    - [Ext] setFeeTo #
    - [Ext] setFeeToSetter #
    - [Ext] routerInitialize #
    - [Ext] routerAddress

 + [Int] IWETH 
    - [Ext] balanceOf
    - [Ext] allowance
    - [Ext] deposit ($)
    - [Ext] transfer #
    - [Ext] withdraw #

 + [Int] IPYE 
    - [Ext] totalSupply
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Lib] Address 
    - [Int] isContract
    - [Int] sendValue #
    - [Int] functionCall #
    - [Int] functionCall #
    - [Int] functionCallWithValue #
    - [Int] functionCallWithValue #
    - [Int] functionStaticCall
    - [Int] functionStaticCall
    - [Int] functionDelegateCall #
    - [Int] functionDelegateCall #
    - [Int] verifyCallResult

 + [Lib] Counters 
    - [Int] current
    - [Int] increment #
    - [Int] decrement #
    - [Int] reset #

 + [Lib] Math 
    - [Int] max
    - [Int] min
    - [Int] average
    - [Int] ceilDiv

 + [Lib] Arrays 
    - [Int] findUpperBound

 +  Context 
    - [Int] _msgSender
    - [Int] _msgData

 +  Ownable (Context)
    - [Pub]  #
    - [Pub] owner
    - [Pub] renounceOwnership #
       - modifiers: onlyOwner
    - [Pub] transferOwnership #
       - modifiers: onlyOwner
    - [Int] _transferOwnership #

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

 + [Int] IERC20Metadata (IERC20)
    - [Ext] name
    - [Ext] symbol
    - [Ext] decimals

 +  ERC20 (Context, IERC20, IERC20Metadata)
    - [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] _spendAllowance #
    - [Int] _beforeTokenTransfer #
    - [Int] _afterTokenTransfer #

 +  ERC20Snapshot (ERC20)
    - [Int] _snapshot #
    - [Int] _getCurrentSnapshotId
    - [Pub] balanceOfAt
    - [Pub] totalSupplyAt
    - [Int] _beforeTokenTransfer #
    - [Prv] _valueAt
    - [Prv] _updateAccountSnapshot #
    - [Prv] _updateTotalSupplySnapshot #
    - [Prv] _updateSnapshot #
    - [Prv] _lastSnapshotId

 + [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

 +  MoonshotMechanism (IMoonshotMechanism)
    - [Pub]  #
    - [Pub] createMoonshot #
       - modifiers: onlyAdmin
    - [Pub] popMoonshot #
       - modifiers: onlyAdmin
    - [Pub] deleteMoonshot #
       - modifiers: onlyAdmin
    - [Pub] updateAdmin #
       - modifiers: onlyAdmin
    - [Ext] getGoal
    - [Ext] getMoonshotBalance
    - [Pub] getMoonshotNameAndValue
    - [Pub] getContractValue
       - modifiers: onlyAdmin
    - [Pub] getDisbursalValue
       - modifiers: onlyAdmin
    - [Int] random
    - [Pub] overrideDisbursalThreshold #
       - modifiers: onlyAdmin
    - [Int] pickMoonshot #
    - [Ext] shouldLaunchMoon
    - [Ext] launchMoonshot #
    - [Int] buyReflectTokens #
    - [Int] sendMFToStakingContractAfterBuyReflectTokens #
    - [Pub] setStakingContractAddress #
       - modifiers: onlyAdmin
    - [Pub] swapToWBNB #
       - modifiers: onlyAdmin
    - [Ext] enableAutoMoonshot #
       - modifiers: onlyAdmin
    - [Ext] rescueBNB #
       - modifiers: onlyAdmin
    - [Ext] rescueToken #
       - modifiers: onlyAdmin

 +  MoonFORCE (IPYE, Context, ERC20, ERC20Snapshot, Ownable)
    - [Pub]  #
       - modifiers: ERC20
    - [Ext]  ($)
    - [Pub] snapshot #
       - modifiers: onlyOwner
    - [Pub] getCurrentSnapshot
       - modifiers: onlyOwner
    - [Pub] totalSupplyAt
       - modifiers: onlyOwner
    - [Int] _beforeTokenTransfer #
    - [Pub] blacklistAddress #
       - modifiers: onlyOwner
    - [Pub] removeFromBlacklist #
       - modifiers: onlyOwner
    - [Pub] decimals
    - [Pub] totalSupply
    - [Pub] balanceOf
    - [Pub] getOwnedBalance
    - [Pub] getCirculatingSupply
    - [Int] _getTokenIndex
    - [Int] _checkPairRegistered
    - [Pub] addPair #
    - [Pub] addOutsideSwapPair #
       - modifiers: onlyOwner
    - [Pub] removeOutsideSwapPair #
       - modifiers: onlyOwner
    - [Ext] setIsStakingContract #
       - modifiers: onlyOwner
    - [Ext] rescueBNB #
       - modifiers: onlyOwner
    - [Ext] rescueToken #
       - modifiers: onlyOwner
    - [Pub] allowance
    - [Pub] approve #
    - [Pub] increaseAllowance #
    - [Pub] decreaseAllowance #
    - [Int] _approve #
    - [Int] getTotalFee
    - [Prv] _takeFees #
    - [Prv] _takeFee #
    - [Prv] calculateFee
    - [Prv] restoreAllFee #
    - [Prv] removeAllFee #
    - [Prv] setSellFee #
    - [Prv] setOutsideBuyFee #
    - [Prv] setOutsideSellFee #
    - [Pub] isExcludedFromFee
    - [Pub] isExcludedFromReward
    - [Pub] excludeFromFee #
       - modifiers: onlyOwner
    - [Pub] includeInFee #
       - modifiers: onlyOwner
    - [Ext] setMaxTxPercent #
       - modifiers: onlyOwner
    - [Ext] setIsTxLimitExempt #
       - modifiers: onlyOwner
    - [Int] checkTxLimit
    - [Prv] _getValues
    - [Pub] depositLPFee #
       - modifiers: onlyExchange
    - [Int] swapToWBNB #
    - [Ext] setIsRewardExempt #
       - modifiers: onlyOwner
    - [Int] _updatePairsFee #
    - [Ext] setReflectionPercent #
       - modifiers: onlyOwner
    - [Ext] setLiquifyPercent #
       - modifiers: onlyOwner
    - [Ext] setMoonshotPercent #
       - modifiers: onlyOwner
    - [Ext] setMarketingPercent #
       - modifiers: onlyOwner
    - [Ext] setBuyBackPercent #
       - modifiers: onlyOwner
    - [Ext] setMarketingAddress #
       - modifiers: onlyOwner
    - [Ext] setLiquifyAddress #
       - modifiers: onlyOwner
    - [Pub] updateMoonshotAddress #
       - modifiers: onlyOwner
    - [Ext] setNewStakingContract #
       - modifiers: onlyOwner
    - [Int] setShare #
    - [Int] addHolder #
    - [Int] removeHolder #
    - [Int] shouldAutoBuyback
    - [Int] triggerAutoBuyback #
    - [Int] buyTokens #
       - modifiers: swapping
    - [Ext] setAutoBuybackSettings #
       - modifiers: onlyOwner
    - [Ext] setBuyBackThreshold #
       - modifiers: onlyOwner
    - [Pub] updateRouterAndPair #
       - modifiers: onlyOwner
    - [Pub] transfer #
    - [Pub] transferFrom #
    - [Int] _transfer #
    - [Prv] _tokenTransfer #





About Solidity Finance

Solidity Finance was founded in 2020 and quickly grew to have one of the most experienced and well-equipped smart contract auditing teams in the industry. Our team has conducted 1000+ solidity smart contract audits covering all major project types and protocols, securing a total of over $10 billion U.S. dollars in on-chain value.
Our firm is well-reputed in the community and is trusted as a top smart contract auditing company for the review of solidity code, no matter how complex. Our team of experienced solidity smart contract auditors performs audits for tokens, NFTs, crowdsales, marketplaces, gambling games, financial protocols, and more!

Contact us today to get a free quote for a smart contract audit of your project!

What is a Solidity Audit?

Typically, a smart contract audit is a comprehensive review process designed to discover logical errors, security vulnerabilities, and optimization opportunities within code. A Solidity Audit takes this a step further by verifying economic logic to ensure the stability of smart contracts and highlighting privileged functionality to create a report that is easy to understand for developers and community members alike.

How Do I Interpret the Findings?

Each of our Findings will be labeled with a Severity level. We always recommend the team resolve High, Medium, and Low severity findings prior to deploying the code to the mainnet. Here is a breakdown on what each Severity level means for the project:

  • High severity indicates that the issue puts a large number of users' funds at risk and has a high probability of exploitation, or the smart contract contains serious logical issues which can prevent the code from operating as intended.
  • Medium severity issues are those which place at least some users' funds at risk and has a medium to high probability of exploitation.
  • Low severity issues have a relatively minor risk association; these issues have a low probability of occurring or may have a minimal impact.
  • Informational issues pose no immediate risk, but inform the project team of opportunities for gas optimizations and following smart contract security best practices.