Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sl1 - Lack of slippage protection during withdrawal in SuperPool and Pool contracts. #356

Open
sherlock-admin3 opened this issue Aug 24, 2024 · 10 comments
Labels
Escalation Resolved This issue's escalations have been approved/rejected Has Duplicates A valid issue with 1+ other issues describing the same vulnerability Medium A Medium severity issue. Reward A payout will be made for this issue Sponsor Disputed The sponsor disputed this issue's validity Won't Fix The sponsor confirmed this issue will not be fixed

Comments

@sherlock-admin3
Copy link

sherlock-admin3 commented Aug 24, 2024

sl1

Medium

Lack of slippage protection during withdrawal in SuperPool and Pool contracts.

Summary

Lack of slippage protection in the SuperPool and Pool could lead to loss of user funds in an event of bad debt liquidation.

Vulnerability Detail

When a user who has deposited assets in one of the pools of the Pool.sol contract wishes to withdraw them, they can do so by calling withdraw(). Under normal conditions, user expects to receive the full deposited amount back or more if the interest accrues in the underlying pool. However, if the pool experiences bad debt liquidation, the totalAssets of the pool are reduced by the amount of bad debt liquidated and the exchange rate worsens.
Pool.sol#L542-L547

// rebalance bad debt across lenders
pool.totalBorrowShares = totalBorrowShares - borrowShares;
// handle borrowAssets being rounded up to be greater than totalBorrowAssets
pool.totalBorrowAssets = (totalBorrowAssets > borrowAssets)
    ? totalBorrowAssets - borrowAssets
    : 0;
uint256 totalDepositAssets = pool.totalDepositAssets;
pool.totalDepositAssets = (totalDepositAssets > borrowAssets)   <<@
    ? totalDepositAssets - borrowAssets  <<@
    : 0;

When a user withdraws, if the pool experiences bad debt liquidation, while the transaction is pending in the mempool, they will burn more shares than they expected.

Consider the following scenario:

  • pool.totalAssets = 2000.
  • pool.totalShares = 2000.
  • Bob wants to withdraw 500 assets, expecting to burn 500 shares.
  • While Bob's transaction is pending in the mempool, the pool experiences a bad debt liquidation and totalAssets drops to 1500.
  • When Bob's transaction goes through, he will burn 500 * 2000 / 1500 = 666.66 shares.

The same issue is present in the SuperPool contract, as the totalAssets() of the SuperPool is dependant on the total amount of assets in the underlying pools a SuperPool has deposited into.

SuperPool.sol#L180-L189

function totalAssets() public view returns (uint256) {
    uint256 assets = ASSET.balanceOf(address(this));
    uint256 depositQueueLength = depositQueue.length;
    for (uint256 i; i < depositQueueLength; ++i) {
        assets += POOL.getAssetsOf(depositQueue[i], address(this));
    }
    return assets;
}

Pool.sol#L218-L227

function getAssetsOf(
    uint256 poolId,
    address guy
) public view returns (uint256) {
    PoolData storage pool = poolDataFor[poolId];
    (uint256 accruedInterest, uint256 feeShares) = simulateAccrue(pool);
    return
        _convertToAssets(
            balanceOf[guy][poolId],
            pool.totalDepositAssets + accruedInterest,
            pool.totalDepositShares + feeShares,
            Math.Rounding.Down
        );
}

When redeeming in the SuperPool, a user will either burn more shares when using withdraw() or receive less assets when using redeem().

Impact

withdraw() in the Pool.sol and both redeem/withdraw in the SuperPool lack slippage protection, which can lead to users loosing funds in the even of bad debt liquidation.

Code Snippet

https://github.com/sherlock-audit/2024-08-sentiment-v2/blob/0b472f4bffdb2c7432a5d21f1636139cc01561a5/protocol-v2/src/Pool.sol#L339-L372
https://github.com/sherlock-audit/2024-08-sentiment-v2/blob/0b472f4bffdb2c7432a5d21f1636139cc01561a5/protocol-v2/src/SuperPool.sol#L281-L286
https://github.com/sherlock-audit/2024-08-sentiment-v2/blob/0b472f4bffdb2c7432a5d21f1636139cc01561a5/protocol-v2/src/SuperPool.sol#L293-L298

Tool used

Manual Review

Recommendation

Introduce minimum amount out for redeem() function and maximum shares in for withdraw() function as means for slippage protection.

@github-actions github-actions bot added Has Duplicates A valid issue with 1+ other issues describing the same vulnerability Medium A Medium severity issue. labels Sep 5, 2024
@sherlock-admin3 sherlock-admin3 added Sponsor Disputed The sponsor disputed this issue's validity Won't Fix The sponsor confirmed this issue will not be fixed labels Sep 10, 2024
@z3s z3s removed the Medium A Medium severity issue. label Sep 15, 2024
@z3s
Copy link
Collaborator

z3s commented Sep 15, 2024

Slippage protection cannot circumvent bad debt

@z3s z3s closed this as completed Sep 15, 2024
@sherlock-admin4 sherlock-admin4 changed the title Massive Seafoam Eel - Lack of slippage protection during withdrawal in SuperPool and Pool contracts. sl1 - Lack of slippage protection during withdrawal in SuperPool and Pool contracts. Sep 15, 2024
@sherlock-admin4 sherlock-admin4 added Non-Reward This issue will not receive a payout and removed Has Duplicates A valid issue with 1+ other issues describing the same vulnerability labels Sep 15, 2024
@kazantseff
Copy link

Escalate,
This issue and #245 should be valid. Slippage protection is not used to circumvent bad debt, but to protect users from loosing value when bad debt occurs.

@sherlock-admin3
Copy link
Author

Escalate,
This issue and #245 should be valid. Slippage protection is not used to circumvent bad debt, but to protect users from loosing value when bad debt occurs.

You've created a valid escalation!

To remove the escalation from consideration: Delete your comment.

You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final.

@sherlock-admin4 sherlock-admin4 added the Escalated This issue contains a pending escalation label Sep 17, 2024
@ruvaag
Copy link

ruvaag commented Sep 28, 2024

This should be invalid and not a duplicate of #245 because the title and description are not coherent.

While the title talks about slippage during withdraw / deposits (which is a separate issue), the description talks about funds lost due to a bad debt liquidation which has nothing to do with slippage

@kazantseff
Copy link

For slippage to occur, the totalAssets of the pool must reduce and exchange rate worsen, this can happen during bad debt liquidation. Otherwise there won't be any slippage as the exchange rate will stay 1:1 and there won't be a need for slippage protection at all.

@cvetanovv
Copy link
Collaborator

Watson has identified an edge case where the user could receive fewer shares than expected during a bad debt liquidation.

In the event of a bad debt liquidation, the pool's total assets decrease, causing the exchange rate to worsen. If a user attempts to withdraw or redeem during this period, they can burn more shares or receive fewer assets than anticipated.

I am planning to accept the escalation and make this issue Medium.

@samuraii77
Copy link

samuraii77 commented Oct 2, 2024

@cvetanovv, hello, could #292 be considered a duplicate? It is for a different functionality in a different part of the code but the root cause is the same and the impact is very similar.

@cvetanovv
Copy link
Collaborator

cvetanovv commented Oct 3, 2024

I can't duplicate them because they have nothing in common.

The problem here is that a user can get fewer tokens when using redeem() or withdrawal() in the event of a bad debt liquidation.

There is nothing like that mentioned in #292. Usually, bots liquidate, and even if a user does it, he is not obliged to do it.
Moreover, everything is different. Different parts of the code. Different fix. The root cause here is the lack of slippage on the bad debt liquidation event. This root cause is missing at #292.

Therefore, I will not duplicate them, and my previous decision will remain.

@WangSecurity WangSecurity added the Medium A Medium severity issue. label Oct 4, 2024
@sherlock-admin2 sherlock-admin2 added Reward A payout will be made for this issue and removed Non-Reward This issue will not receive a payout labels Oct 4, 2024
@WangSecurity
Copy link

WangSecurity commented Oct 4, 2024

Result:
Medium
Has duplicates

@WangSecurity WangSecurity reopened this Oct 4, 2024
@sherlock-admin2
Copy link
Contributor

sherlock-admin2 commented Oct 4, 2024

Escalations have been resolved successfully!

Escalation status:

@sherlock-admin3 sherlock-admin3 removed the Escalated This issue contains a pending escalation label Oct 4, 2024
@sherlock-admin4 sherlock-admin4 added the Escalation Resolved This issue's escalations have been approved/rejected label Oct 4, 2024
@sherlock-admin3 sherlock-admin3 added the Has Duplicates A valid issue with 1+ other issues describing the same vulnerability label Oct 11, 2024
@sherlock-admin3 sherlock-admin3 removed Sponsor Disputed The sponsor disputed this issue's validity Won't Fix The sponsor confirmed this issue will not be fixed labels Oct 20, 2024
@sherlock-admin3 sherlock-admin3 added Sponsor Disputed The sponsor disputed this issue's validity Won't Fix The sponsor confirmed this issue will not be fixed labels Oct 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Escalation Resolved This issue's escalations have been approved/rejected Has Duplicates A valid issue with 1+ other issues describing the same vulnerability Medium A Medium severity issue. Reward A payout will be made for this issue Sponsor Disputed The sponsor disputed this issue's validity Won't Fix The sponsor confirmed this issue will not be fixed
Projects
None yet
Development

No branches or pull requests

9 participants