Prisma Finance Incident - March 28, 2024 - Post-Mortem

Prisma Finance Incident - March 28, 2024 - Post-Mortem

Prisma Finance Incident - March 28, 2024 - Post-Mortem

Jun 7, 2024

Summary

  • A vulnerability in both versions of the MigrateTroveZap (mkUSD and ULTRA) contract of Prisma Finance led to a loss of 3,479.24 ETH, or approximately $12 million USD.

  • In response, the Prisma Finance emergency multi-sig has paused the protocol’s operations.

  • The vulnerable contract is a special-purpose contract designed to migrate user positions from one trove manager to another.

  • The vulnerability affects Prisma Trove owners who approved this contract to manage their Trove’s position via setDelegateApproval(MigrateTroveZap, True) on the BorrowerOperations contract.

  • The issue occurred when an exploiter made a transaction that, with a lack of input validation in the onFlashloan function, allowed the exploiter to manipulate the contract’s behavior and take a portion of a Trove owner’s collateral.

  • As a result, the exploiter was able to close a Trove owners Trove, withdraw the collateral (wstETH), and reopen the Trove with the same debt (mkUSD) but less collateral, taking the difference.

  • A thorough investigation is conducted to identify the root cause and implement necessary fixes.

  • There was a primary exploiter (Exploiter 1) followed by copycat exploiters.

  • Trove owners should verify they have revoked any active approvals for the MigrateTroveZap.

Background

Prisma Finance deployed a contract called MigrateTroveZap to facilitate trove owners migrating their Troves (collateralized debt positions) to new TroveManager contracts. This was part of a broader system upgrade announced in March 2024.

As part of these updates, Prisma deprecated the original 4 LST (Liquid Staking Token) Vaults with a 4% interest rate cap, replacing them with new LST Vaults, allowing for higher rates. The 3 LRT (Liquid Restaking Token) Vaults were also deprecated and replaced with new versions optimized for more efficient redemptions.

Prisma built the MigrateTroveZap helper contract to ensure a smooth transition, enabling trove owners to seamlessly move their Trove positions from the old TroveManager contracts to the new ones without needing to close positions, remove liquidity, or incur additional costs. The contract uses flash loans to close the user’s old Trove and immediately open a new Trove with the same collateral and debt in the new TroveManager, all in one atomic transaction.

These changes followed Prisma’s standard DAO governance process, with the migration starting with the deployment of the MigrateTroveZap contract on March 20th, 2024, and the first trove owners migrating Troves using the helper contract from March 23rd onwards.

Details of the Incident

On March 28th, 2024, at 11:25 UTC, an exploiter (Exploiter 1](https://etherscan.io/address/0x7e39e3b3ff7adef2613d5cc49558eab74b9a4202)) made a transaction in the MigrateTroveZap contract, resulting in a total transfer of around 3,257 ETH (approximately $11 million USD) from some Prisma Finance Trove owners. This was followed by two other exploiters (Exploiter 2 and Exploiter 3) that managed to transfer a smaller amount of ~121 and ~52 wstETH, respectively. The incident was made possible due to insufficient input validation in the onFlashloan() function, which allowed the Users to manipulate input data and execute unintended contract behavior.

Affected Trove owners had previously migrated from TroveManager v1 to v2 using the migration contract. This involved setting delegate approval in the BorrowerOperations contract with MigrateTroveZap as an argument. Although the vulnerability affects both the MigrateTroveZap contract for mkUSD and ULTRA and all TroveManagers, only the wstETH Troves for mkUSD were targeted.

The Prisma team has advised Trove owners to revoke delegate approval and announced a convenient process to do so on the Prisma app. The team has also paused the protocol, disallowing new collateral to be added and blocking further damage. Once unpaused, any open zap approvals are still open to this issue.

Detailed timeline (March 28th)

  • 11:15 UTC: Exploiter 1 wallet is funded via FixedFloat exchange

  • 11:22 UTC: Exploiter 1 Exploit contract is deployed

  • 11:25 UTC: Exploiter 1 calls function 0x82be0b96, initiating the transaction.

  • 11:29 UTC: The Prisma Team is alerted by a community member on Discord.

  • 11:51 UTC Prisma announces a potential incident on Twitter.

  • 12:11 UTC: Prisma advises users to revoke delegate approval on both LST and LRT BorrowerOperations

  • 12:41 UTC: Exploiter 2 executes its first transaction.

  • 12:49 UTC: Exploiter 3 executes its first transaction.

  • 12:51 UTC: Emergency multi-sig calls Paused()

General Logic

The exploiters took advantage of the vulnerability through the following steps:

  1. The exploiters bypassed the migrate function and called the flash loan directly with carefully crafted input data.

  2. The flash loan’s callback function, onFlashloan(), was called.

  3. The lack of proper checks allowed the exploiters to close a Trove owner’s Trove and immediately reopen it within the same TroveManager. The transaction caused the owner’s position to be closed and reopened, resulting in the Trove owner having a new position with the same debt but less collateral and the difference in collateral sitting in the zap contract.

  4. The exploiters then opened a new Trove and used the MigrateTroveZap contract to migrate it, effectively using the remaining collateral for their own Trove.

  5. Finally, the exploiters closed their Trove and took the profits.

Example Tx

The incident was conducted in a series of transactions that targeted vulnerable Troves individually. The diagram shown below is a simplified funds flow of the first transaction, whereby the wstEthTroveManagerV2 (0x1cc) sends a victim’s collateral to MigrateTroveZap, sends it back to wstEthTroveManagerV2, and finally sends the amount to the Contract (0xd99).

upload_f00cca34a138a127f96d580fb8d944cc

Source: Phalcon


The exploiter closed the active Trove of the TroveOwner, which had a Trove open with 1745.08 wstETH collateral and 1,442,100 mkUSD debt. The Trove owner’s Trove was immediately reopened with 463.18 wstETH collateral and 1,443,398 mkUSD debt. This reduced the collateral ratio from around 498% to 132%, putting it at risk of liquidation.

upload_1f77f72d852a93df3513b5b6f0d5ad54

Source: Phalcon


The exploiter proceeded to open a small Trove with one wstETH collateral and 2,000 mkUSD debt. They migrated the position using MigrateTroveZap and reopened a Trove that inherits the remainder of the wstETH in the contract. The reopened Trove had 1,282.79 wstETH collateral and 2,001.8 mkUSD debt.

upload_d451f06266a34e31026dc4d385991f82 (1)

Source: Phalcon


Finally, the exploiter closed the Trove, receiving 1,282.79 wstETH, and paid back all necessary flash loans to Balancer and Prisma.

upload_bad908e25c61ad34d3410ec79d025eae

Source: Phalcon

The root cause of the vulnerability was twofold:

  1. By directly calling the flashloan() function, the exploiter could manipulate other Trove Managers’ positions.

  2. The contract allowed for a mismatch between the collateral in the initial position and the collateral in the new position, with the difference being susceptible to being taken.

upload_5d6cf09f0deb57c7a61add1e31ba3805

Flashloan function of MigrateTroveZap - Source: ContractReader.io

Consequences of the protocol being paused

Pausing in Prisma is a security mechanism that halts certain operations during emergencies or unforeseen issues. When paused, functions like opening new vaults, increasing collateral or debt, and depositing into Stability Pools are disabled. However, users can still withdraw collateral to minimize the risk of locked funds. In the incident’s context, pausing likely prevented further incidents by disabling new Troves and collateral addition.

Key Addresses

Name Address Exploiter 1 (EOA) 0x7E39E3B3ff7ADef2613d5Cc49558EAB74B9a4202 Exploiter 2 (EOA) 0x7Fe83f45e0f53651b3ED9650d2a2C67D8855e385 Exploiter 3 (EOA) 0x7C9FC6E2B908e858F30c5c71a20273315Efd5cf8 Exploiter 1 contract 0xd996073019c74b2fb94ead236e32032405bc027c Exploiter 2 Contract 0x4148310fe4544e82f176570C6c7B649290a90E17 Exploiter 3 Contract 0x1b8A9F9F5a1d9cB1C28D9120F9c2bD073ccfAC04 MigrationTroveZap (mkUSD) 0xcC7218100da61441905e0c327749972e3CBee9EE MigrationTroveZap (ULTRA) 0xC3eAf094e2586965244aB6534f6Dc69c6C16b5D5 mkUSD Contract 0x4591dbff62656e7859afe5e45f6f47d3669fbb28 New wstETH TroveManager 0x1cc79f3f47bfc060b6f761fcd1afc6d399a968b6 Borrower Operations (LST) 0x72c590349535AD52e6953744cb2A36B409542719 Prisma Emergency msig 0x7A28A80DcE1733944Db5dC50dc2c5147eC993C5A

Incident proceeds

Exploiter 1 Funds Recipient Amount Hash 0x2d413803a6eC3Cb1ed1a93BF90608f63b157507a 757.69 ETH LINK 0x57f7033F84894770F876bf64772E7EBA48990D65 1,500 ETH LINK 0x5d0064f3B54C8899Ab797445551058Be460C03C6 1,000 ETH LINK

Exploiter 2 Funds Recipient Amount Hash 0x7fe83f45e0f53651b3ed9650d2a2c67d8855e385 138.19 ETH LINK

Exploiter 3 Funds Recipient Amount Hash 0x7C9FC6E2B908e858F30c5c71a20273315Efd5cf8 52.32 wstETH LINK

Affected wallets

Exploiter 1 | Count: 11

Addresses Collateral Pre-Incident Collateral Post-Incident Incident Timestamp 0x56A201b872B50bBdEe0021ed4D1bb36359D291ED 1745.08 wstETH 463.18 wstETH 11:25:11 AM +UTC 0x774bb9306df1cd921eb842b1388c78f75e6ef79f 172.18 wstETH 149.36 wstETH 11:28:11 AM +UTC 0xcbfdffd7a2819a47fcd07dfa8bcb8a5deacc9ea8 824.6 wstETH 192.12 wstETH 11:29:11 AM +UTC 0xc47fae56f3702737b69ed615950c01217ec5c7c8 40 wstETH 11.69 wstETH 11:36:47 AM +UTC 0x3b15cec2d922ab0ef74688bcc1056461049f89cb 107.18 wstETH 18.89 wstETH 11:43:23 AM +UTC 0x1b72bac3772050fdcaf468cce7e20deb3cb02d89 166.41 wstETH 47.49 wstETH 11:45:47 AM +UTC 0x3b15cec2d922ab0ef74688bcc1056461049f89cb 18.89 wstETH 18.97 wstETH 11:48:11 AM +UTC 0x16f570e93fdbc3a4865b7740deb052ee94d87e15 113.6 wstETH 32.4 wstETH 11:53:47 AM +UTC 0xf9ca66ef84c773fab422562ab41b1ee8d4397418 47.3 wstETH 15.48 wstETH 11:54:47 AM +UTC 0xc487370895f6e8f5b62d99bf1472c95a94073379 377.2 wstETH 95.6 wstETH 12:07:47 PM +UTC 0x9fceded3a0c838d1e73e88dde466f197df379f70 356.28 wstETH 102.12 wstETH 12:12:47 PM +UTC

Exploiter 2 | Count: 11

Addresses Collateral Pre-Incident Collateral Post-Incident Incident Timestamp 0x14b30b46ec4fa1a993806bd5dda4195c5a82353e 4.22 wstETH 1.21 wstETH 12:42:11 PM +UTC 0x19562df3e7fd2ae7af4e6bd288b04c2c90405212 31.22 wstETH 9.15 wstETH 12:46:35 PM +UTC 0x1b004189e64d5b2f71d5be554470e6c49e10123b 21.74 wstETH 5.98 wstETH 12:46:59 PM +UTC 0x3b82ee6c15b212ed69d5795bcd957e136eaa4bff 13.02 wstETH 3.45 wstETH 12:47:11 PM +UTC 0x409c6c5ec5c479673f4c09fb80d0f182fcff643e 3.8 wstETH 0.93 wstETH 12:47:23 PM +UTC 0xc47fae56f3702737b69ed615950c01217ec5c7c8 11.69 wstETH 11.78 wstETH 12:49:11 PM +UTC 0xf8d1c9ab49219f7acf7b1d84705e5aea3b8ce0aa 17.85 wstETH 17.93 wstETH 12:49:35 PM +UTC 0x19562df3e7fd2ae7af4e6bd288b04c2c90405212 9.15 wstETH 9.23 wstETH 12:50:23 PM +UTC 0x409c6c5ec5c479673f4c09fb80d0f182fcff643e .99 wstETH 1.06 wstETH 12:50:35 PM +UTC 0x4a3fced7c536e39ca5292a024ee66c9b45b257ec 87.93 wstETH 19.85 wstETH 12:50:47 PM +UTC 0x19562df3e7fd2ae7af4e6bd288b04c2c90405212 9.23 wstETH 9.3 wstETH 12:51:47 PM +UTC

Exploiter 3 | Count: 3

Addresses Collateral Pre-Incident Collateral Post-Incident Incident Timestamp 0xf8d1c9ab49219f7acf7b1d84705e5aea3b8ce0aa 70.3 wstETH 17.85 wstETH 12:49:35 PM +UTC 0x3b82ee6c15b212ed69d5795bcd957e136eaa4bff 3.45 wstETH 3.52 wstETH 12:50:23 PM +UTC 0x409c6c5ec5c479673f4c09fb80d0f182fcff643e 0.93 wstETH .99 wstETH 12:50:35 PM +UTC

Actions Needed

Users with open Vaults should head over to the Revoke Approval page and follow the instructions there.

Next Steps

The Prisma team along with many others are continuing the investigation and working to communicate with the Exploiters.

While retrieving all Trove owners funds is our main focus right now, unpausing the protocol will be part of the next steps once we are sure that all positions are safe.

Further steps will be published once a plan is worked out.

Acknowledgments

Thanks to Dan from HyperNative Labs, who was the first one to directly reach out to us.

We extend our gratitude to Llama Risk and Wavey for their invaluable assistance in compiling information and crafting this report. Their dedication and expertise significantly enhanced the quality and depth of our analysis.

We are immensely thankful to our friends and contributors who joined us in the War Room, offering their unwavering support and insights from the inception of our response. Their collaboration and swift action were instrumental in navigating through these challenges.

We are glad to be counting on the support and expertise of MixBytes, our historical security partner.

Special recognition goes to ZachXBT for his in-depth assistance. His observations proved indispensable in addressing the issue promptly and decisively.

Thanks to everyone who reached out to offer help and assistance. The solidarity from the space that we felt was an incredible support and will help face the next challenges.

Resources