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

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

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

Curve

Curve

Mar 29, 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).

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.

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.

Source: Phalcon

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

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.

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

Incident proceeds

Exploiter 1 Funds Recipient

  • 0x2d413803a6eC3Cb1ed1a93BF90608f63b157507a 757.69 ETH LINK

  • 0x57f7033F84894770F876bf64772E7EBA48990D65 1,500 ETH LINK

  • 0x5d0064f3B54C8899Ab797445551058Be460C03C6 1,000 ETH LINK

Exploiter 2 Funds Recipient

  • 0x7fe83f45e0f53651b3ed9650d2a2c67d8855e385 138.19 ETH LINK

Exploiter 3 Funds Recipient

  • 0x7C9FC6E2B908e858F30c5c71a20273315Efd5cf8 52.32 wstETH LINK

Affected wallets

Exploiter 1 | Count: 11

Exploiter 2 | Count: 11

Exploiter 3 | Count: 3

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

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).

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.

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.

Source: Phalcon

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

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.

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

Incident proceeds

Exploiter 1 Funds Recipient

  • 0x2d413803a6eC3Cb1ed1a93BF90608f63b157507a 757.69 ETH LINK

  • 0x57f7033F84894770F876bf64772E7EBA48990D65 1,500 ETH LINK

  • 0x5d0064f3B54C8899Ab797445551058Be460C03C6 1,000 ETH LINK

Exploiter 2 Funds Recipient

  • 0x7fe83f45e0f53651b3ed9650d2a2c67d8855e385 138.19 ETH LINK

Exploiter 3 Funds Recipient

  • 0x7C9FC6E2B908e858F30c5c71a20273315Efd5cf8 52.32 wstETH LINK

Affected wallets

Exploiter 1 | Count: 11

Exploiter 2 | Count: 11

Exploiter 3 | Count: 3

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