On September 7, the Nemo protocol was exploited, resulting in a financial loss of approximately $2.59 million. The attack's core was the concurrent exploitation of a dual vulnerability:
A flash_loan
function, intended for internal use, was erroneously exposed as a public function.
After comprehensive analysis from multiple parties, the flash loan is not the primary attack vector, and actually not that relevant as the attacker could have loaned funds from somewhere else. However, it is important to clarify that it acts as an "accelerant."
A query function, get_sy_amount_in_for_exact_py_out
, contained a flaw that allowed for unauthorized modification of the contract's internal state.
An in-depth investigation has traced the procedural root cause to January of this year. During the window between MoveBit's initial audit and the final revised report, a Nemo developer(The developer mentioned in this article is the same) introduced this new, unaudited feature into the codebase submitted for review. Consequently, a version of the contract containing unaudited code was deployed to the mainnet. The governance root cause was the protocol's reliance on a single-signature address for upgrades, which failed to prevent the deployment of code that had not undergone rigorous scrutiny. But the most important thing is that the version confirmed by the audit company was not used by the developer.
During this period, another unfortunate development is that after receiving the notification from Asymptotic team regarding the issue with the update_current_exchange_rate
function (as referenced in C-2), the developer did not attach sufficient importance to it or carry out the necessary fix. In fact, this issue could have been resolved with Asymptotic's support.
Attack Vector Analysis
flash_loan
function. By combining a call to borrow_pt_amount
with repeated calls to swap_exact_pt_for_sy
and update_price
, they manipulated the internal state. This culminated in a call to mint_py
to extract a large quantity of SY before using repay_pt_amount
to settle the loan, thereby successfully draining substantial SY assets from the SY/PT liquidity pool.Claim_Reward
function, which relied on the manipulated, incorrect price.TLDR
The Asymptotic team identified issue C-2 in their preliminary audit report, and a researcher who also noted the vulnerability introduced by the Sui Foundation security team. During subsequent feature development, our team did not adequately address this security concern in a timely manner, leading to the introduction and eventual exploitation of the vulnerability.
Late 2024 - Initial Audit Phase
In the code version submitted for the initial audit, the flash_loan
function was correctly configured as an internal, non-callable function. While awaiting the final audit report, our development team iterated on features to optimize the product and prepare for future expansion.
flash_loan
: To maximize composability, our team drew inspiration from leading EVM protocols like Aave and Uniswap, reserving a flash_loan
capability. The vision was to allow other protocols (e.g., lending platforms, DEXs) to utilize our pool's assets for uncollateralized atomic arbitrage or liquidations, generating additional fee revenue for our LPs. This was a forward-thinking design embracing the "DeFi Lego" ethos, but we critically underestimated its security risks, heavy reliance on oracles and used the public method incorrectly.get_sy_amount_in_for_exact_py_out
: To enhance our native Swap's quoting mechanism, we added this function to provide a more precise on-chain pricing tool and reduce user slippage. However, a critical implementation error occurred where a function intended for read-only purposes was coded with write capabilities. This was the key vulnerability exploited in the attack.January 5, 2025 - Flawed Audit Submission Process
A significant procedural error occurred after we received MoveBit's initial audit report. While addressing the identified issues, we integrated the new, unaudited features (including the 1.public flash_loan
2.get_sy_amount_in_for_exact_py_out
and write without permission ) into the final codebase. This mixed version, containing both "fixed issues" and "new unaudited features," was subsequently submitted to MoveBit for final review without explicitly highlighting the scope of the new additions.
January 6, 2025 - Report Acquisition and Deployment
Unfortunately, this developer did not mention this to the Movebit and Nemo teams internally. Instead, he communicated with the Movebit team and obtained the final audit report, only modifying the previous report. At the same time, he did not use the confirmation hash in the audit report for deployment, but instead upgraded and deployed it separately. On January 6, 2025, using the single-signature address 0xf55cc609b13e87470d3da78d39ad6f84458a8059eb06aa66f94103d775e8a663
, he deployed contract version 0xcf34697ad898bb0f96b2750653208150d89ead6bf224549bebc2b6654e5c5204
, which contained the unaudited features. This version remained active in our production environment until the exploit occurred. The attacker used this vulnerability in this attack.
April 3, 2025 - Transition to Multi-Sig Upgrade Protocol The Nemo team formally implemented a new Standard Operating Procedure (SOP) for contract upgrades. This mandated that all mainnet contract upgrades and critical parameter changes must be executed via the Nemo Foundation's multi-signature wallet, a requirement that was also integrated into our audit specifications. Unfortunately, this developer only transferred the cap of the contract with the unaudited code vulnerability mentioned above to the multi-signature management, and did not choose to deploy and hand over the version confirmed in the audit report.
Aug 11,2025 -Received the report from Asymptotic team, but not taken seriously
The developer's feedback on this matter is that, at the time, there were two contracts—Nemo Vault and Nemo Market—and priority was given to addressing Nemo Vault. As a result, the repair priority of Nemo Market was affected.
September 7, 2025 (Day of the Attack):
get_sy_amount_in_for_exact_py_out
and flash_loan
functions.Remove Liquidity
bug and a simple oracle attack, we identified the root cause as a combined flash loan and price manipulation exploit. Fund tracing revealed that the majority of stolen funds had been bridged to Ethereum via CCTP.