QuickSwap and StellaSwap contest - 0x52's results

A concentrated liquidity DEX with dynamic fees.

General Information

Platform: Code4rena

Start Date: 26/09/2022

Pot Size: $50,000 USDC

Total HM: 13

Participants: 113

Period: 5 days

Judge: 0xean

Total Solo HM: 6

Id: 166

League: ETH

QuickSwap and StellaSwap

Findings Distribution

Researcher Performance

Rank: 1/113

Findings: 4

Award: $11,445.66

🌟 Selected for report: 2

πŸš€ Solo Findings: 2

Findings Information

🌟 Selected for report: cccz

Also found by: 0x52

Labels

bug
duplicate
3 (High Risk)
sponsor confirmed

Awards

4882.9086 USDC - $4,882.91

External Links

Lines of code

https://github.com/code-423n4/2022-09-quickswap/blob/15ea643c85ed936a92d2676a7aabf739b210af39/src/core/contracts/AlgebraPool.sol#L416-L485

Vulnerability details

Impact

Detailed description of the impact of this finding.

Proof of Concept

AlgebraPool.sol#L227-L230

uint32 _liquidityCooldown = liquidityCooldown; if (_liquidityCooldown > 0) { require((_blockTimestamp() - lastLiquidityAddTimestamp) >= _liquidityCooldown); }

The code above from AlgebraPool.sol#_recalculatePosition causes a revert if the liquidity has been added or removed with in the specified cooldown period. _recalculatePosition is called whenever a position is minted (added to) or burned (removed from). Mint allows a user to add liquidity to a different user, which allows an adversary to DOS a specific user from depositing or withdrawing their liquidity. The adversary would front run the mint or burn transaction with a malicious mint for a small amount. This would initiate the cooldown period causing the user's deposit or withdraw to fail.

Concentrated liquidity positions are particularly vulnerable to impermanent loss. An adversary could take advantage of this to block the user causing greater impermanent loss to a user that is trying to withdraw a position. This would mean that this DOS vector timed correctly could lead to loss of funds for the user being DOS'd.

Tools Used

I don't see any reason why mint needs to allow specifying a different recipient. It should be remove to resolve this DOS vector

#0 - 0xean

2022-10-02T20:54:22Z

Attack path looks valid. If we assume the cooldown period to be something near half a day (a day being the max), then 2 calls per day could lock a users liquidity for relatively cheaply.

#1 - sameepsi

2022-10-04T06:13:24Z

duplicate of #70

#2 - 0xean

2022-10-04T13:36:33Z

will use #70 as canonical issue, closing this as dupe.

Findings Information

🌟 Selected for report: 0x52

Labels

bug
2 (Med Risk)
sponsor acknowledged

Awards

3255.2724 USDC - $3,255.27

External Links

Lines of code

https://github.com/code-423n4/2022-09-quickswap/blob/15ea643c85ed936a92d2676a7aabf739b210af39/src/core/contracts/AlgebraPool.sol#L891-L949

Vulnerability details

Impact

Flashloan users forced to pay higher fees than expected

Proof of Concept

The first swap of the block sets the fee that will apply to all other actions during that block, including the fee that will be applied to flashloans. If a swap occurs in the same block before the flashloan, the fee taken from the flashloan will be different than expected potentially much different. This could be used by an adversary to force a flashloan user to pay higher fees. They would frontrun the flashloan call with a swap that would push the fees higher. This is dependent on the current state of the swap beforehand but liquidity providers would have a strong incentive to monitor the pool to maximize their profits.

Tools Used

Manual Review

Using the swap fee as the flashloan fee seems counterintuitive to me. It doesn't cause any impermanent loss to the liquidity providers, which is what the dynamic fee is designed to offset. There are two possible solutions to this. The first solution would be to allow the flashloan user to specify a max fee they will pay. The other solution, which I believe makes more sense, is to just use a flat fee on flashloans. This provides more consistent outcomes for flashloan users, making the product more attractive.

#0 - IliaAzhel

2022-10-04T17:28:12Z

Indeed, the flashloan fee may depend on previous transactions in the block. However, fee can not only increase, but also decrease.

Findings Information

🌟 Selected for report: 0x52

Labels

bug
2 (Med Risk)
sponsor acknowledged

Awards

3255.2724 USDC - $3,255.27

External Links

Lines of code

https://github.com/code-423n4/2022-09-quickswap/blob/15ea643c85ed936a92d2676a7aabf739b210af39/src/core/contracts/AlgebraPool.sol#L626-L673

Vulnerability details

Impact

Exact output functionality does not exist for fee on transfer tokens

Proof of Concept

require((amountRequired = int256(balanceToken0().sub(balance0Before))) > 0, 'IIA');

Exact output swaps are signaled by setting amountRequired to a negative number. When calling AlgebraPool#swapSupportingFeeOnInputTokens amount required is set to the difference is token balances before and after which will always be positive. Since amountRequired can't be negative, the exact output functionality is impossible to use for those tokens.

Tools Used

Manual Review

Fee on transfer tokens are messy and there is no standard implementation to query the fee from the token contract. Ultimately support for these tokens should be added through either user inputs (i.e. allowing high slippage) or a specialized router

Lines of code

https://github.com/code-423n4/2022-09-quickswap/blob/15ea643c85ed936a92d2676a7aabf739b210af39/src/core/contracts/AlgebraPool.sol#L626-L673

Vulnerability details

Impact

User is forced to pay token transfer fees twice, once when taking payment and once when returning extra

Proof of Concept

Fee on transfer tokens take a fee each time the token is transferred. AlgebraPool#swapSupportingFeeOnInputTokens implements two transfers, one for the main payment and one for the refund. This causes the users to have to pay token transfer fees twice.

Tools Used

Support for fee on transfer tokens should be added through either user inputs (i.e. allowing high slippage) or a specialized router

#0 - vladyan18

2022-10-04T10:59:39Z

We cannot determine how many tokens with fee on transfer a pool will receive until it has received them. On the other hand, the return of tokens can only occur under special circumstances, such as a set limitSqrtPrice.

#1 - 0xean

2022-10-04T15:27:30Z

Going to downgrade to QA, hard problem to solve given slippage, etc. I think this is more of a consequence of FOTs design

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax Β© 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter