# Incident Report: Omnichain Swap & Deposit Exploit (April 20, 2024) ## Summary - Merkle Trade launched the Swap & Deposit feature which involved an immutable smart contract with vulnerabilities in its unlimited approvals. - Our internal monitoring system identified abnormal activity in user addresses engaging with the subject smart contract, flagged to the team after 10 addresses were impacted for $19K. - In response, we a) promptly reverted the front-end to prevent further approvals, b) announced the vulnerability along with a detailed revoke approval guide, c) implemented a pop-up modal to alert users who had not revoked approvals, and d) flagged the attacker addresses to major CEXes while contacting security partners for further forensics. - Majority of addresses had revoked the approval by D+3, with 4 wallets remaining as of writing. - We are fully reimbursing all 10 impacted addresses for the exploited $19,412 via team funds after confirming the approvals are revoked. ## Overview On April 18th, we deployed the Swap & Deposit feature which enhances the user onboarding flow by swapping user’s stablecoin of choice and bridging that to the user’s Aptos account. On April 20th, our internal monitoring system identified abnormal patterns when 10 addresses were exploited. We responded by reverting the front-end while announcing the vulnerability details and revoke guide in all our social channels. Additionally, we worked with security partners to track the perpetrator and notified relevant parties including centralized exchanges. All 10 impacted addresses will be 100% reimbursed via team funds. As of writing, there are 4 wallets remaining that need to revoke approvals which the team is actively following up on. Learning from this experience, the team will implement more extensive security measures to ensure that such exploits do not happen again. ## Incident Details A vulnerability was identified in the smart contract deployed on April 18th 09:25 UTC. It was exploited by the attacker(s) in the duration of April 20th 08:43-15:19 UTC, resulting in the loss of $19,412 from 10 of our users’ wallets. The vulnerable contract address is 0xBf2685d3b22F9E4753aeAcbc8f14fC73965C17f2, same address across Ethereum, Arbitrum, Optimism, Polygon, BSC, Avalanche. As of April 23rd, 06:35 UTC, there are 4 vulnerable wallets that have not revoked allowance to the contract. ### **Timeline** - **April 18th, 09:25 UTC:** Swap & Deposit feature released - **April 20th, 08:43-15:19 UTC:** Exploit transactions occurred - **April 20th, 11:19 UTC:** Team became aware of the situation - **April 20th, 13:58 UTC:** Feature reverted from frontend - **April 20th, 17:21 UTC:** 1st announcement ([Twitter](https://twitter.com/Merkle_Trade/status/1781734932232233274)) - **April 20th, 18:38 UTC:** “Revoke Needed” modal added to frontend - **April 20th, 19:25 UTC:** 2nd announcement and a revoke guide published ([Twitter](https://twitter.com/Merkle_Trade/status/1781766139372282011), [Guide](https://t.co/X0dtuJlt05)) - **April 21st, 08:44 UTC:** 3rd announcement ([Twitter](https://twitter.com/Merkle_Trade/status/1781967351573094911)) - **April 22nd, 12:47 UTC:** Improved “Revoke Needed” modal - **April 22nd, 14:32 UTC:** 4th announcement ([Twitter](https://twitter.com/Merkle_Trade/status/1782417279596007685)) ### **Vulnerability** The `SwapBridge` contract is designed to execute a token swap and then send the resulting token to the LayerZero bridge in a single transaction. To accommodate various swap contracts, the `swapAndSendToAptos` function accepts `swapTarget` and `swapBytes` as parameters. These specify the swap contract and the calldata for the swap, which is executed before sending the asset to the bridge. The vulnerability arises because the contract does not whitelist the `swapTarget`. It can be called with arbitral smart contract address and calldata, even those unrelated to swap functionality. Additionally, users had to approve the `SwapBridge` contract for the ERC20 tokens they wanted to swap before executing the `swapAndSendToAptos` function. ### **Attack Details** The attacker exploited above vulnerability by setting the `swapTarget` as the ERC20 contract address and using calldata that corresponded to the `ERC20.transferFrom` function. This function call transferred the approved ERC20 tokens from the users’ wallets directly to the attacker, leveraging the tokens that users had approved for the contract. **Sample Transaction ([0x462c…a4dd](https://arbiscan.io/tx/0x462cab29471473852a7743cfd5cf3c0cdbaa7e05a85a3431bfca3668c50fa4dd) on Arbitrum)** 1. Expoiter calls an unknown function of a contract they deployed before. 2. The exploiter’s contract makes an inner transaction to `SwapBridge.swapAndSendToAptos` with the following calldata: - Raw Calldata ``` 0xf316d227000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc80000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc800000000000000000000000000000000000000000000000000000000000000010000000000000000000000004bbc40c1e5f4ad7fc74ec0ecccc61954c98a557f000000000000000000000000fd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb900000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000006423b872dd0000000000000000000000007ef5bae4719680e5196dff91142429e6fca97a840000000000000000000000004bbc40c1e5f4ad7fc74ec0ecccc61954c98a557f000000000000000000000000000000000000000000000000000000002533e11c00000000000000000000000000000000000000000000000000000000 ``` - Parsed ``` function swapAndSendToAptos _fromToken: 0xff970a61a04b1ca14834a43f5de4533ebddb5cc8 _fromAmount: 1 _toToken: 0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8 _toAmount: 1 _aptosAddress: 0x0000000000000000000000004bbc40c1e5f4ad7fc74ec0ecccc61954c98a557f _swapTarget: 0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9 _swapBytes: 0x23b872dd0000000000000000000000007ef5bae4719680e5196dff91142429e6fca97a840000000000000000000000004bbc40c1e5f4ad7fc74ec0ecccc61954c98a557f000000000000000000000000000000000000000000000000000000002533e11c ``` The `_swapTarget` value (0xFd08…Cbb9) in the inner transaction is the address of the USDT smart contract on Arbitrum, and the `_swapBytes` value represents the calldata for the `transferFrom` function, specifically `transferFrom(0x7ef5baE4719680E5196DFf91142429e6fca97A84, 0x4bbC40C1e5f4aD7FC74EC0EcCCC61954c98A557F, 624156956)` 3. The `swapAndSendToAptos` function then executes the `transferFrom` call which transfers 624.156956 USDT from the user’s wallet (0x7ef5…7A84) to the perpetrator’s address (0x4bbC…557F). ### **Full List of Exploit Transactions** | attacker address | chain | evm tx hash | amount | asset | evm address | | --- | --- | --- | --- | --- | --- | | 0x6b27b029b5f7df1438e0b8ef5317e890f7f96be6 | Arbitrum One | 0x462cab29471473852a7743cfd5cf3c0cdbaa7e05a85a3431bfca3668c50fa4dd | 624.156956 | USDT | 0x7ef5baE4719680E5196DFf91142429e6fca97A84 | | 0x6b27b029b5f7df1438e0b8ef5317e890f7f96be6 | Arbitrum One | 0xb0dfb5262ec212f4d7dcd92e22f3cd91099b75b423ebee4c2d03d1dd848632e6 | 350.330786 | USDC | 0xF157D6a482A982ED9E39Eece2137810d578486F8 | | 0x6b27b029b5f7df1438e0b8ef5317e890f7f96be6 | Arbitrum One | 0x270b8ac6ac6c5c38df2ee5d62ecb80d464b13244ab6d8690e6dbadab6950e4ff | 1892.158368 | USDC.e | 0x922197Fd26290E3AF3dA0C35e7f4F299d95E8741 | | 0xb7025bd929b7421ba2ab601b80e1b9a53c8332dc | Arbitrum One | 0x14c7c54a191980d0c06461d9324c2d5e6c146f9f4684e92aff9ac8a69af921f2 | 3.478753 | USDC.e | 0x1D22717220E811E8ff59B776F329a06a29e257e5 | | 0xb7025bd929b7421ba2ab601b80e1b9a53c8332dc | Arbitrum One | 0xe529ffcd7e957de4f766ca253c143a0c6e3e76d260349b3582746b54149ab49f | 3.737669 | USDC.e | 0x537723B21cf71b3f16256b50161F7EceDf6B746d | | 0xb7025bd929b7421ba2ab601b80e1b9a53c8332dc | Arbitrum One | 0x947d413b2e65b8a657baccd5ce9420ef365763a9e36439befea8a583c6ee1371 | 28.888938 | USDC.e | 0xf6Ad8B833FeC26Af07C71A8a1b8C0c340f1848e2 | | 0xb7025bd929b7421ba2ab601b80e1b9a53c8332dc | Arbitrum One | 0x3ba887b61a6fc811bf5913894e48afc3a63f9657127b319c332f64bfe539ed84 | 2.439515 | USDC | 0xe4387caf746532f719303Bccb22cAf5fEb457C0e | | 0xb7025bd929b7421ba2ab601b80e1b9a53c8332dc | Arbitrum One | 0x35f9ed7d3f09e29899ca79cf2c3560c5398b2ab2804a5bad491296cdd3909655 | 3.316036 | USDC | 0xa2F402Cf20F56AFB8C379D9d9750d8e7dBd6f236 | | 0xb7025bd929b7421ba2ab601b80e1b9a53c8332dc | Arbitrum One | 0xfd3fa57249a29ec4b3768be649b2d47e711a2583d667f39d281b01a370198f98 | 40.3155 | USDC | 0x01f010fdC02745A7c3bce0DDCf958DD56a840096 | | 0x6b27b029b5f7df1438e0b8ef5317e890f7f96be6 | Arbitrum One | 0xda3d88aed66e28e77f10d8fa377a6e5383ac7a78910c09ce81fd182baf822ae2 | 16463.97649 | USDC | 0x62dCa5060c7043c838504fF9144A5bdf201A7d55 | ## Immediate Steps Taken ### Frontend Reversion We reverted the frontend immediately upon becoming aware of the exploit to prevent further user interactions with the contract. As a result, no additional wallets have been impacted by the exploit after April 20th, 13:58 UTC. ### Guiding Users to Revoke the ERC20 Approval Initially, over 80 addresses had approved the vulnerable contract with infinite allowance. Since the contract could not be paused or upgraded, it became imperative for all affected users to revoke the approval. We have communicated this through announcements on Twitter, Discord, and Telegram, along with a complete list of affected addresses and [a detailed guide](https://merkle-trade.notion.site/Vulnerable-Addresses-Swap-Deposit-Approval-27053021fe794da3b20456f7d46e56ea) on revoking approvals. Additionally, we directly reached out to some users after identifying their social media accounts. Furthermore, a non-dismissable pop-up was implemented on the platform to ensure that the applicable accounts revoke their ERC20 approval before they can resume any further actions: ![revoke-modal](https://hackmd.io/_uploads/Sk7HQ9IWR.gif =x280) As of April 23rd, 13:02 UTC, 4 wallets still have allowances left to the vulnerable contract. If you interacted with the deposit feature between April 18th and 20th, please consult the [revoke guide](https://merkle-trade.notion.site/Vulnerable-Addresses-Swap-Deposit-Approval-27053021fe794da3b20456f7d46e56ea) and follow the steps to ensure your wallet is secure. ### Tracking Efforts on the Perpetrator ![track](https://hackmd.io/_uploads/rk8rQcU-R.jpg =x280) With the assistance of white hat hacker groups, we are currently scrutinizing all traces from the perpetrator to find any association with their KYC'd CEX account or other leads that might be linked to their identity. To this end, we have submitted relevant information to centralized exchanges such as Binance, OKX, and Bybit, and are exploring options to enlist the help of local authorities for pursuing lawful actions against the perpetrator. ## Preventive Measures Firstly, we are implementing a stringent internal development policy regarding reviews and audits before the deployment of smart contracts. In this particular incident, despite the contract’s small scope (fewer than 100 LOC) and having been independently reviewed by three external Solidity engineers, the measures previously taken proved to be insufficient. Thus, going forward, we are mandating audits by reputable security firms before deploying all smart contracts, regardless of their size or apparent complexity. Additionally, we will enforce stricter internal guidelines for preventive practices across the board. This will include refraining from requiring infinite ERC20 approvals from the frontend, implementing freeze capabilities, and precisely tailoring the smart contract’s functionality to existing use cases. By focusing strictly on the current requirements, we aim to minimize the scope of the contract, thereby reducing opportunities for its misuse for malicious purposes. Lastly, we will enhance our monitoring systems to detect any anomalies in transactions involving our contracts. The impact of this vulnerability could have easily escalated if not for the internal monitoring system we implement for our new features. We will further develop this capacity to enable our team to be alerted to potential incidents more promptly, ensuring rapid response to any unforseen issues that may arise. ## Closing Remarks We extend our deepest gratitude to our security partner, MoveBit, and white hat hacker groups who assisted us, as well as our community for their support and understanding throughout the ordeal. We are fully committed to learning from this incident and are taking decisive steps to enhance our security measures, preventing such vulnerabilities in the future. Your trust is our top priority, and we are dedicated to upholding it with the highest standards of security and transparency.