$SAFEMOON has grown more than 15,000% since its launch, its market cap has surpassed $6 billion, and liquidity in dex-swaps is currently higher than $200,000,000. HashEx figured out what exactly 2 million investors are putting on the line.
We have conducted an audit and discovered a total of 12 vulnerabilities, 2 of which are critical, and 3 pose a high risk.
These vulnerabilities allow:
- Setting the commissions for the transfer of $SAFEMOON up to 100%
- Rug pulling
- Excluding holders from commissions distribution
- Temporarily blocking token transfers
- Rendering the token smart contract permanently inoperable
At least 4 vulnerabilities work in combination. Their sequential exploitation may multiply inflicted damage.
About SafeMoon
SafeMoon exists on BEP-20 smart contract. For each $SAFEMOON transfer the smart contract takes a 5% commission, which is later being distributed among all of the token holders. The mechanic works in a way that both encourages and rewards users for holding the tokens so that they could receive more tokens.
Capitalization: $3,526,035,528
Holders: 2,194,087
Liquidity in pairs: $167,854,727
Network: Binance Smart Chain
Smart-contract: 0x8076c74c5e3f5852037f31ff0093eeb8c8add8d3
Contract owner: 0x79c4Af7c43F500b9cCBa9396d079cC03DFcAFdA1
Token transfers: 6,578,967
Data provided for May 21, 2021
Further, we are going to explore the most obvious methods of abusing found vulnerabilities and one attack scenario.
A Rugpull for $20,000,000
A rugpull is the act of liquidity theft performed by the developer. The liquidity is being “pulled” from the pool, which gives this event its name “rug pull”.
Safemoon smart contract owner is an externally owned account, that’s being controlled by a specific person. This account keeps liquidity pool tokens with a market value of $20,000,000. The sum is constantly going up because the smart contract transfers part of the transfer commissions to the owner account.
In case the owner address is compromised, a rugpull of over $20,000,000 can happen at any moment. Because it’s about 15% of all liquidity that is being held in liquidity pools, the $SAFEMOON exchange rate can go down rapidly.
Even if the developer transfers the ownership to a token burning address, it still can be returned via function call. So any malicious user could return the ownership with vulnerability #01 Temporary ownership renounce.
Black List of Rewards
Vulnerability #03, excludeFromReward () abuse allows to exclude certain wallets from rewards distribution or put them back in. This way the transfer rewards can be received only on the wallets that haven’t been excluded.
The attack code, which demonstrates the possibility of distribution of 30% of the balance in favor of the included wallets, is described in Appendix C of the audit.
100% token transfers to the reward pool
The contract includes set functions:
_taxFee
_liquidityFee
_maxTxAmount
In these functions, it’s possible to set any unit256 values.
For instance, with _taxFee == 100%
a transfer will be subject to 100% commission. Instead of transferring the token to the receiver, the whole sum ends up on the common reward pool.
The detailed vulnerability description is available in the audit: #02 No Safeguard for Fees and maxTxAmount.
Blocking of any transfers of $SAFEMOON token
Vulnerability #04 Excluded Length Problem
The mechanism of removing addresses from auto-yielding implies a loop over excluded addresses for every transfer operation or balance inquiry. This may lead to extreme gas costs up to the block gas limit and may be avoided only by the owner restricting the number of excluded addresses.
In an extreme situation with a large number of excluded addresses transaction gas may exceed maximum block gas size and all transfers will be effectively blocked.
Moreover, includeInReward()
function relies on the same for()
loop which may lead to irreversible contract malfunction.
Backdoor Synergy
On their own, vulnerabilities #01, #02 и #03 can inflict serious damage on the holders. However, under circumstances, these vulnerabilities may form a chain ideal for an attack strategy.
1. Front-Run transaction
a. When a user sends the transaction to the BSC network, it joins the queue.
b. Depending on the gas fee that is set, the transaction will wait for the miners to add it into the block.
c. The higher is the gas fee, the sooner the transaction is added to the block.
d. If the contract owner notices that a holder is transferring $MOON tokens, they can send the transaction with the changed condition of the contract variables before the user’s one, due to a higher gas fee.
2. In the Front-Run transaction a malicious user sets:
a. a specific commission for the $SAFEMOON token transfer
b. excludes the biggest holders from the commissions’ distribution
3. Upon receiving 100% from the transfer to their own wallet, a malicious user might set the commission back at the previous value and include the excluded wallets back into the distribution list.
4. To hide the actions, after the procedure is completed, the ownership of the contract can be temporarily moved to the burning wallet.
5. An optional possibility after the procedure is blocking the network to wait for a large number of transfers to form a queue.
In this example, the biggest damage may be inflicted to the biggest holders, and transfers of large sums of $SAFEMOON token, because in an attempt to save the resources and to attract as little attention as possible, it makes sense to exploit the backdoor only during large transfers.
We’ve reached out to Safemoon team, and received a comment from their CTO Thomas Smith:
These are not issues that we can update with a deployed contract without a hardfork, we have been made aware of these by Certik. Functions like excludeFromReward and the same for excludeFromFee are used for exchange hot wallets so that users are not unfairly penalized for participating with CEXs. Addressing these other issues, such as ownership renounce being able to be taken back by the contract deployer, we are never going to renounce and have made our stance on that clear in the past. Internally we have policies and procedures around how the contract operates to alleviate risk of mishandling values, however you will never see us modify fees or maxTx. Thank you for the audit, we will keep your findings in mind if/when we hardfork.
Conclusion
Recently there were quite a few incidents when big and reputable (at least at a first glance) companies locked up billions of dollars of investors’ funds exploiting smart contract vulnerabilities like these. That is why we believe that it’s important to shed light on these security concerns and to make sure that a decentralized community is aware of the risks. At the end of the day, the beauty of decentralization is not in trusting someone to make sure that your money is safe, but rather making sure that your money is safe because there are no tools available for anyone to manipulate it.
To read the contents of a transaction one needs to possess specific knowledge. The source code of a smart contract is available to everyone, so anyone can check the contents of a transaction. However, enough time might pass before the community notices the malicious activity, and informs the rest of the investors about it.
Not everyone who notices the vulnerability will report it.
Definitely, not everyone who notices it will be willing to publish the information first.
You can find the detailed audit report with the code examples and vulnerabilities descriptions on Medium or Github.