SafeMoon Exploit: An Objective Incident Analysis
This report is a comprehensive post-mortem analysis of a recent incident involving the SafeMoon V2 token, which resulted in a significant loss of funds due to an exploited vulnerability in the smart contract code.
This article is the opinion of the author and was not created by, at the request of, or in collaboration with SafeMoon, LLC or any of its affiliates. The information provided herein is intended for informational purposes only and should not be considered as professional advice, endorsement, or a recommendation to engage in any investment or financial activities. The author makes no representations or warranties regarding the accuracy, completeness, or reliability of any information presented in this article. Readers should exercise their own due diligence and consult with professional advisors before making any financial decisions or taking any action based on the content of this article. The author shall not be held liable for any losses, damages, or consequences that may arise from the use of, or reliance on, the information provided herein.
![](https://miro.medium.com/v2/resize:fit:700/0*eTRcErcsXTYt8ulQ.png)
1. A time-based review of the incident facts
In order to provide a clear understanding of the sequence of events leading up to and during the incident, we will begin with a time-based review of the incident as it unfolded. This section will detail the chronological sequence of events that ultimately led to the exploitation of the SafeMoon protocol, resulting in $8.9 million being drained from its liquidity pool on March 28, 2023.
The incident unfolded in the following sequence:
- Mar-27–2023 08:48:18 AM +UTC: The SafeMoon V2 Deployer Address initiated a contract call to the SafeMoon V2 Proxy Admin Contract to upgrade the implementation contract for the SafeMoon V2 token. This upgrade was intended to introduce a new
burn()
function for bridging purposes, allowing tokens to be transferred between different blockchain networks securely. The transaction hash for this call is0xcb8573807b1db40215840f690eeba6af6ec8fcc5a98eb5d545d40f7f775b0d1b
, included in block26823719
. - Mar-28–2023 10:54:28 AM +UTC: Another contract call was initiated by the SafeMoon V2 Deployer Address to upgrade the implementation contract once again. This upgrade modified the
burn()
function, adding afrom
address parameter, which created an exploit vector. The new burn function allowed any address to call the function and transfer tokens from any arbitrary address to thebridgeBurnAddress
without requiring the owner’s approval. The transaction hash for this call is0x3307500ebaf50fb72c82a62829c8a0b20d8a076e9beae1ff97d87ba32843e219
, included in block26854756
. - Mar-28–2023 ~07:26:27 PM +UTC: An exploiter, using the address
0x97226254ff489f3257e68222f184ac2b6e20a4ff
, attempted to drain the liquidity pool of tokens by invoking the burn function through the contract0x53f29b8f4a4af0731b8d3b2c273d9602a0cf41ac
. The transaction hash for this call is0xbcf5e30c164837b5d7c42fd7e33e47a0072dc014e7f0a67aa7710af49d0ce53b
, included in block26864891
. - Mar-28–2023 07:26:27 PM +UTC: However, a frontrunner, using the address
0x286E09932B8D096cbA3423d12965042736b8F850
, outpaced the exploiter using a Maximum Extractable Value (MEV) bot. The MEV bot allowed the frontrunner to execute the attack first, resulting in the transfer of28,364.49
BNB (worth approximately $8.9M at the time) via the contract0xa1fAe685c8abF938EB706DedABbcfFbFf3b3D7Da
. The transaction hash for this call is0x48e52a12cb297354a2a1c54cbc897cf3772328e7e71f51c9889bb8c5e533a934
, included in block26864890
.
This series of events led to the loss of the vast majority of BNB from the SafeMoon V2 token’s liquidity pool, causing a major impact on token holders due to a catastrophic collapse in the token’s decentralized liquidity.
Following the initial exploitation of the SafeMoon V2 token’s vulnerability, other unknown actors, who had determined the nature of the exploit, began to take advantage of the situation. These actors started triggering the exploitable burn()
function on various random wallets, including the burn wallet itself. These tokens were then transferred to the SafeMoon V2 Deployer Address, which was set as the bridgeBurnAddress
in the smart contract.
This unexpected turn of events exacerbated the already complicated situation, as it led to a further loss of tokens for unsuspecting wallet holders and the burn wallet.
2. Analysis of the exploitable code
The initial burn function, introduced on March 27th, had the following form:
function burn(uint256 amount) public {
_tokenTransfer(msg.sender, bridgeBurnAddress, amount, 0, false);
}
This burn()
function allowed the sender (the token holder) to burn a specified amount of their tokens by transferring them to the bridgeBurnAddress
address. The _tokenTransfer()
function facilitated the transfer of tokens while ensuring that various internal checks and safety measures were in place. This implementation provided a secure way to burn tokens for bridging purposes.
However, on March 28th, the burn()
function was modified, introducing an exploit vector:
function burn(address from, uint256 amount) public {
_tokenTransfer(from, bridgeBurnAddress, amount, 0, false);
}
The modified burn function added the from
address parameter, allowing any address to call the function and transfer tokens from any arbitrary address to the bridgeBurnAddress
address. This change enabled an attacker to move tokens without the approval of the token holder, effectively bypassing the security measures in place.
The rationale for modifying the burn function has not been officially disclosed as of the time this article was written. However, based on the blockchain activity observed before and after its implementation, this change may have been made to integrate with an external bridge contract.
Approximately 8 hours and 32 minutes after the vulnerability was introduced, it was exploited.
To exploit this vulnerability, the attacker constructed a contract call using the address 0x97226254ff489f3257e68222f184ac2b6e20a4ff
and the contract 0x53f29b8f4a4af0731b8d3b2c273d9602a0cf41ac
. The attacker attempted to drain the liquidity pool of tokens by repeatedly invoking the burn()
function, transferring tokens from arbitrary addresses to the bridgeBurnAddress
, which was configured to be the SafeMoon V2 Deployer Address.
Before the attacker could execute their transaction fully, a frontrunner utilizing an MEV bot outpaced the attacker and executed a similar attack first, transferring 28,364.49
BNB (worth approximately $8.9M at the time) via the contract 0xa1fAe685c8abF938EB706DedABbcfFbFf3b3D7Da
to the address 0x286E09932B8D096cbA3423d12965042736b8F850
.
3. Liquidity pool impact analysis
The exploit, as previously described, enabled the attacker to forcibly remove tokens from the liquidity pool. This action had a significant impact on the balance between the token and BNB in the pool. To understand how this affected the token price, we must examine the constant product market maker formula (k=x∗y) used by decentralized exchanges that use the Uniswap v2 interface, which includes PancakeSwap and the SafeMoonSwap on the BNB Smart Chain Network.
In this formula, k represents a constant value, x represents the amount of one token (e.g., SafeMoon V2) in the liquidity pool, and y represents the amount of another token (e.g., BNB) in the pool. The formula ensures that the product of x and y remains constant as the ratio between the tokens changes, which in turn affects the token prices.
When the attacker removed tokens from the liquidity pool using the exploit, the balance of SafeMoon V2 tokens (x) in the pool decreased significantly. This action changed the “constant” k, as the exploit itself was not a function of the automated market maker (AMM). The new k value was based on the reduced amount of SafeMoon V2 tokens and the unchanged amount of BNB in the pool. The altered token ratio forced the price of SafeMoon V2 tokens to skyrocket, as fewer tokens in the pool implied a higher price per token.
The higher token price, based on the new k value, allowed the attacker to sell a relatively small number of SafeMoon V2 tokens in the liquidity pool in exchange for an enormous amount of BNB. This action drained the liquidity pool of its BNB backing, causing a liquidity crisis.
4. Frontrunning analysis
For context, frontrunning occurs when a malicious actor observes a pending transaction in the validation mempool and constructs their own transaction with a higher gas fee, causing it to be processed before the original transaction.
In this incident, the original attacker attempted to exploit the vulnerability with the burn()
function. However, a frontrunner was able to outpace the attacker by deploying a Maximum Extractable Value (MEV) bot.
The MEV bot allowed the frontrunner to craft a similar transaction with a higher gas fee, which ultimately paid 1.246
BNB in transaction fees. This higher fee ensured that their transaction would receive priority treatment in the mempool. Ultimately, it was prioritized and processed by the Ankr Validator before the attacker’s transaction. (Surprisingly, the frontrunner’s transaction was the only non-overhead transaction picked up and processed in block 26864890
!)
As a result, the frontrunner was able to execute the exploit before the attacker to collect 28,364.49
BNB (worth approximately $8.9M at the time). This action thwarted the attacker’s plan and redirected the stolen funds to the frontrunner’s control.
As of the time of writing, the frontrunner has transferred 27,380
BNB to the 0x237D58596F72C752a6565858589348D0fCe622ed
address, where it currently sits. There has been on-chain communication between wallets controlled by the frontrunner and the SafeMoon team, which might suggest some form of negotiation. However, no funds have been reclaimed thus far.
5. How the exploitable code was introduced
Upgradeable proxies are a design pattern used in the development of smart contracts to enable updates and modifications to the contract logic without affecting the state or storage of the contract. This pattern provides a level of flexibility that traditional immutable smart contracts do not have, allowing developers to address bugs, security vulnerabilities, or add new features after the contract has been deployed. However, the use of upgradeable proxies also introduces new risks and potential attack vectors which need to be carefully managed and mitigated (I wrote an article about the pros and cons of upgradeable proxies here).
The upgradeable proxy pattern typically consists of two main components: the proxy contract and the implementation contract. The proxy contract is responsible for forwarding function calls and data to the implementation contract, which contains the actual business logic. By changing the implementation contract address that the proxy contract points to, developers can effectively upgrade or modify the contract logic.
In the case of SafeMoon V2, the token contract address is a proxy contract is 0x42981d0bfbAf196529376EE702F2a9Eb9092fcB5
, and the proxy admin contract is 0xa6f662994bf46627f12c023b22a28618eb7ce893
. The SafeMoon V2 Deployer address at 0x678ee23173dce625a90ed651e91ca5138149f590
had ownership of the proxy, allowing it to initiate upgrades to the implementation contract.
While upgradeable proxies may provide benefits, they also introduce risks and potential attack vectors:
- Centralization of control: One of the key features of blockchain technology is decentralization. However, upgradeable proxies introduce a level of centralization, as the owner of the proxy contract has the power to change the implementation contract. This central point of control could be a target for attackers or lead to misuse of power by the owner.
- Increased complexity: The upgradeable proxy pattern adds complexity to the smart contract development process. The separation of logic between the proxy and implementation contracts may introduce new vulnerabilities, making it harder to reason about the security and behavior of the contract.
- Human error: As the contract logic can be modified, there is a higher risk of human error leading to the introduction of exploitable code. In the case of SafeMoon V2, the change in the burn function inadvertently created a vulnerability that allowed any address to transfer tokens from any arbitrary address.
- Governance and transparency: The process of upgrading the implementation contract must be transparent and well-governed. Without a clear process for proposing, reviewing, and approving changes, there is a risk of misuse or unintended consequences resulting from upgrades.
6. Suggested process mitigation strategies
As a response to this incident, and to minimize the future risks associated with upgradeable proxies and ensure the security and stability of smart contracts, several mitigation strategies can be employed. These strategies aim to reduce the likelihood of introducing exploitable code and enhance the overall governance and transparency of the upgrade process.
- Multi-signature ownership: Implementing multi-signature wallet ownership for the proxy admin contract can help distribute control and decision-making among multiple trusted parties. This approach reduces the risk of a single point of failure and ensures that any upgrades to the implementation contract require consensus among the wallet owners.
- Comprehensive unit testing: Thorough unit testing of smart contract code is essential to ensure that all functions and logic perform as intended. Automated testing frameworks should be used to validate the functionality, security, and performance of both the proxy and implementation contracts.
- Code review process: A formal code review process should be established to evaluate any proposed changes to the implementation contract. This process should involve multiple developers who are experienced with smart contract development and security, ensuring that all potential risks and vulnerabilities are identified and addressed.
- Quality assurance processes: Quality assurance (QA) processes should be in place to validate the overall functionality and security of the smart contract system. These processes may include manual testing, end-to-end testing, and integration testing with other smart contracts to ensure that all components interact as expected.
- Deployment signoffs: Before deploying a new implementation contract or upgrading an existing one, a signoff process should be in place to ensure that all required testing, code review, and QA processes have been completed. This signoff should involve multiple stakeholders, such as developers, security experts, and project managers, to confirm that the contract is ready for deployment.
- Regular security audits: Regular security audits should be conducted by reputable third-party firms to identify potential vulnerabilities and confirm that the smart contract system adheres to industry best practices. These audits should be performed before deployment, as well as after any significant upgrades to multiple interacting contracts.
- Open-review period with a bug bounty: When proposing a new implementation contract or an upgrade to an existing one, an open-review period should be implemented to allow for public scrutiny and feedback. During this period, the contract code should be available for public review, and a bug bounty program should be in place to incentivize the community to identify and report any potential vulnerabilities.
- Transparent governance and decision-making: To enhance trust and confidence in the smart contract system, governance and decision-making processes should be transparent and well-documented. This includes the process for proposing upgrades, reviewing code, conducting security audits, and deciding on deployment. Clear communication channels should be established to keep stakeholders informed about any changes and the rationale behind them.
7. Worst-Case Liquidity Remediation Steps
In the event that the majority of the drained funds are not recovered, the SafeMoon team would have to consider a worst-case scenario for reintroducing liquidity into the ecosystem. Addressing this situation effectively is time-sensitive, as it would help to restore investor confidence and stabilize the token’s price. The following steps outline a potential plan for liquidity reintroduction:
- Source of BNB and tokens: The funds needed to reintroduce liquidity would have to be sourced from various reserves held by the SafeMoon team, as well as incentivized contributions from community members and supporters. This could include a combination of BNB, SafeMoon tokens, and other assets.
- Size of the new liquidity pool: The new liquidity pool should be sized appropriately to ensure that it can support the token’s trading volume and minimize price volatility. While it may be challenging to fully replace the lost liquidity, the new pool should be as close to the original size as possible to maintain stability.
- Liquidity reintroduction method: At first glance, reintroducing liquidity in tranches, as suggested by the SafeMoon team, might appear to be a cautious and measured approach. However, this method could potentially lead to unintended consequences. A smaller liquidity pool can introduce significant volatility. For example, an initial sell-off by large token holders (whales) could put tremendous pressure on the token’s price and effectively hold these whales hostage due to the potential price impact. To mitigate this risk, it may be more suitable to reintroduce liquidity all at once, while carefully monitoring the token’s price and trading activity. This approach would help maintain the token’s price stability and minimize the potential for unintended consequences.
- Potential volatility introduced by a smaller liquidity pool: A smaller liquidity pool can lead to increased price volatility, as buy and sell orders have a more significant impact on the token’s price. To address this, the SafeMoon team could implement mechanisms such as liquidity provider incentives, which encourage users to provide liquidity in exchange for rewards. This would help to increase the size of the liquidity pool and stabilize the token’s price.
- Pausing plans for the new bridging system: In light of the recent exploit and the need to stabilize the main liquidity pool on the BNB Smart Chain, it may be advisable to temporarily postpone any plans to introduce the new bridging system. This would allow the SafeMoon team to concentrate their efforts on addressing the immediate concerns surrounding the liquidity pool and ensuring the stability of the token’s price. Once the main liquidity pool has been adequately stabilized and restored, the team could then resume the development and implementation of the new bridging system. Adopting this cautious approach could help prevent any further disruptions and enable a more controlled and secure expansion of the SafeMoon ecosystem.
8. Conclusion
The incident involving the SafeMoon V2 token highlights the importance of diligent security practices and thorough governance procedures in the realm of smart contracts and DeFi. As we have explored in this report, multiple factors contributed to the exploit, including weaknesses in the code, insufficient testing, and gaps in the code review and quality assurance processes. Additionally, the use of upgradeable proxies and implementation contracts, while providing valuable flexibility, can also introduce risks and vulnerabilities if not managed properly.
To address these challenges and prevent future incidents, it may be advisable for SafeMoon to adopt a robust set of mitigation strategies, such as multi-signature wallet ownership for the proxy admin contract, comprehensive unit testing, a rigorous code review process, and transparent governance and decision-making. The SafeMoon V2 incident serves as a reminder of the critical need for vigilance, transparency, and continuous improvement in the DeFi space.
David Wyly is the CEO of Decentra, Inc (which includes brands such as the All For One crypto mobile app), Director of Engineering for Dappd, LLC, a Blockchain Consultant and Principal Software Engineer, and serves on the Blockchain and Digital Innovation Task Force for the State of Utah.