sherlock-audit / 2023-07-perennial-judging

2 stars 1 forks source link

feelereth - frontrunning vulnerability in the code between calling update() and _update(). #89

Closed sherlock-admin closed 1 year ago

sherlock-admin commented 1 year ago

feelereth

high

frontrunning vulnerability in the code between calling update() and _update().

Summary

The issue is that between calling update() and _update(), there is a window where the state is settled but the user's deposit/redeem has not been processed yet. An attacker could watch for update() calls with large deposit/redeem amounts. After the state is settled but before update() is called, the attacker could make their own call to update() to deposit/redeem first and frontrun the user's intended deposit/redeem.

Vulnerability Detail

The issue occurs between the _settle() and _update() calls in update().

_settle() settles the global and local state of the vault up to the latest checkpoint. This updates the global shares, assets, etc.

Then _update() actually processes the user's deposit, redeem and claim.

So after _settle(), the global state reflects the new settled amounts, but before _update(), the user's intended deposit/redeem has not yet been processed.

This creates an opening for a frontrunning attack:

Impact

The attacker can drain substantial assets from the vault by redeeming right after a large deposit. Or the attacker could deposit right before a large redeem, diluting the redeeming user's shares.

Code Snippet

https://github.com/sherlock-audit/2023-07-perennial/blob/main/perennial-v2/packages/perennial-vault/contracts/Vault.sol#L204-L213 https://github.com/sherlock-audit/2023-07-perennial/blob/main/perennial-v2/packages/perennial-vault/contracts/Vault.sol#L213 https://github.com/sherlock-audit/2023-07-perennial/blob/main/perennial-v2/packages/perennial-vault/contracts/Vault.sol#L215

Tool used

Manual Review

Recommendation

the _update() call logic should be moved into the update() function directly, removing the vulnerable window between _settle() and _update()

sherlock-admin commented 1 year ago

3 comment(s) were left on this issue during the judging contest.

141345 commented:

x

darkart commented:

Invalid

panprog commented:

invalid because _update is internal function called inside update(), attacker can't call it while the other user's transaction is not finished yet