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

bughuntoor - User can sandwich their own position close to get back all of their position fees #94

Open
sherlock-admin2 opened this issue Sep 9, 2024 · 12 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 High A High severity issue. Reward A payout will be made for this issue Sponsor Confirmed The sponsor acknowledged this issue is valid

Comments

@sherlock-admin2
Copy link
Contributor

sherlock-admin2 commented Sep 9, 2024

bughuntoor

High

User can sandwich their own position close to get back all of their position fees

Summary

User can sandwich their own position close to get back all of their position fees

Vulnerability Detail

Within the protocol, borrowing fees are only distributed to LP providers when the position is closed. Up until then, they remain within the position.
The problem is that in this way, fees are distributed evenly to LP providers, without taking into account the longevity of their LP provision.

This allows a user to avoid paying fees in the following way:

  1. Flashloan a large sum and add it as liquidity
  2. Close their position and let the fees be distributed (with most going back to them as they've got majority in the pool)
  3. WIthdraw their LP tokens
  4. Pay back the flashloan

Impact

Users can avoid paying borrowing fees.

Code Snippet

https://github.com/sherlock-audit/2024-08-velar-artha/blob/main/gl-sherlock/contracts/positions.vy#L156

Tool used

Manual Review

Recommendation

Implement a system where fees are gradually distributed to LP providers.

@github-actions github-actions bot added the Medium A Medium severity issue. label Sep 11, 2024
@sherlock-admin3 sherlock-admin3 changed the title Kind Banana Sloth - User can sandwich their own position close to get back all of their position fees bughuntoor - User can sandwich their own position close to get back all of their position fees Sep 11, 2024
@sherlock-admin3 sherlock-admin3 added the Reward A payout will be made for this issue label Sep 11, 2024
@KupiaSecAdmin
Copy link

Escalate

This is invalid, FEES.update function is called after every action, so when the liquidity of flashloan is added, the accrued fees are distributed to prev LP providers.

@sherlock-admin3
Copy link
Contributor

Escalate

This is invalid, FEES.update function is called after every action, so when the liquidity of flashloan is added, the accrued fees are distributed to prev LP providers.

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 11, 2024
@spacegliderrrr
Copy link
Collaborator

Comment above is simply incorrect. Fees.update doesn't actually make a change on the LP token value - it simply calculates the new fee terms and makes a snapshot at current block.

The value of LP token is based on the pool reserves. Fees are actually distributed to the pool only upon closing the position, hence why the attack described is possible.

@rickkk137
Copy link

rickkk137 commented Sep 16, 2024

invalid
it is intended design

def f(mv: uint256, pv: uint256, ts: uint256) -> uint256:
  if ts == 0: return mv
  else      : return (mv * ts) / pv
def g(lp: uint256, ts: uint256, pv: uint256) -> uint256:
  return (lp * pv) / ts

Pool contract uses above formola to compute amount of LP token to mint and also burn value for example:
pool VEL-STX:
VEL reserve = 1000
STX reserve = 1000
VEL/STX price = $1
LP total_supply = 1000
pv stand for pool value and ts stand for total_supply and mv stand for mint value
LP_price = ts / pv = 1000 / 1000 = $1
its mean if user deposit $1000 into pool in result get 1000 LP token
and for burn
burn_value = lp_amount * pool_value / total_supply and based on above example
total_supply=2000
pool_value=2000
because user deposit $1000 into pool and mint 1000lp token

the issue want to say mailicious user with increase lp price can retrieve borrowing_fee ,but when mailicious users and other users closes their profitable positions pool_value will be decreased[the protocol pay users' profit from pool reserve],hence burn_value become less than usual state

requirment internal state for attack path:

  • mailicious user's position be in loss[pool value will be decreased because user collateral will be added to pool reserve]
  • other user don't close their profitable positions in that block
  • flashloan's cost be low

@WangSecurity
Copy link

I see how it can be viewed as the intended design, but still, the user can bypass the fees essentially and LPs lose them, when they should've been to receive it. Am I missing anything here?

@rickkk137
Copy link

attack path is possible when user's position is in lose and loss amount has to be enough to increase the LP price , note that if loss amount be large enough the position can be eligible for liquidation and the user has to close his position before liquidation bot

@spacegliderrrr
Copy link
Collaborator

@WangSecurity Your comment is correct. Anytime the user is about to close their position (whether it be unprofitable, neutral or slightly profitable), they can perform the attack to avoid paying the borrowing fees, essentially stealing them from the LPs.

@WangSecurity
Copy link

attack path is possible when user's position is in lose and loss amount has to be enough to increase the LP price , note that if loss amount be large enough the position can be eligible for liquidation and the user has to close his position before liquidation bot

So these are the constraints:

  1. Loss should be relatively large so it increases the LP price.
  2. The attacker has to perform the attack before the liquidation bot liquidates their position which is also complicated by the private mempool on Bob, so we cannot see the transaction of the liquidation bot.

Are the above points correct and is there anything missing?

@deadrosesxyz
Copy link

No, loss amount does not need to be large. Attack can be performed on any non-profitable position, so the user avoids paying fees.

@WangSecurity
Copy link

In that case, I agree that it's an issue that the user can indeed bypass the fees and prevent the LPs from receiving it. Also, I don't see the pre-condition of the position being non-profitable as an extensive limitation. Moreover, since it can be any non-profitable position, then there is also no requirement for executing the attack before the liquidation bot (unless the position can be liquidated as soon as it's non-profitable).

Thus, I see that it should be high severity. If something is missing or these limitations are extensive in the context of the protocol, please let me know. Planning to reject the escalation, but increase severity to high.

@WangSecurity WangSecurity added High A High severity issue. Has Duplicates A valid issue with 1+ other issues describing the same vulnerability and removed Medium A Medium severity issue. labels Sep 24, 2024
@WangSecurity
Copy link

Result:
High
Has duplicates

@sherlock-admin2 sherlock-admin2 removed the Escalated This issue contains a pending escalation label Sep 24, 2024
@sherlock-admin3 sherlock-admin3 added the Escalation Resolved This issue's escalations have been approved/rejected label Sep 24, 2024
@sherlock-admin4
Copy link
Contributor

Escalations have been resolved successfully!

Escalation status:

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 High A High severity issue. Reward A payout will be made for this issue Sponsor Confirmed The sponsor acknowledged this issue is valid
Projects
None yet
Development

No branches or pull requests

8 participants