Timeswap contest - Beepidibop's results

Like Uniswap, but for lending & borrowing.

General Information

Platform: Code4rena

Start Date: 20/01/2023

Pot Size: $90,500 USDC

Total HM: 10

Participants: 59

Period: 7 days

Judge: Picodes

Total Solo HM: 4

Id: 206

League: ETH

Timeswap

Findings Distribution

Researcher Performance

Rank: 8/59

Findings: 2

Award: $3,251.16

Gas:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: chaduke

Also found by: 0xcm, Beepidibop

Labels

bug
3 (High Risk)
satisfactory
upgraded by judge
duplicate-121

Awards

3202.6177 USDC - $3,202.62

External Links

Lines of code

https://github.com/code-423n4/2023-01-timeswap/blob/ef4c84fb8535aad8abd6b67cc45d994337ec4514/packages/v2-token/src/TimeswapV2LiquidityToken.sol#L193

Vulnerability details

Proof of Concept

collect() uses the wrong paramenters when calling ITimeswapV2Pool.transferFees(). It uses long0Fees, long1Fees, and shortFees instead of param.long0FeesDesired, param.long1FeesDesired, and param.shortFeesDesired. The former 3 are defined in the function's returns paramenters and aren't mutated before calling ITimeswapV2Pool.transferFees(). They all default to zero which would trigger a revert since TimeswapV2Pool.transferFees() reverts when 0 fees are being transferred on line 167

Code snippet where the parameters default to 0

Code snippet where transferFees() revert

Impact

This means users who mints liquidity tokens will be forfeiting their fees since collect() will always be calling ITimeswapV2Pool.transferFees() with 0s as inputs. So I think a medium risk is warranted since users are losing funds.

Recommendation

Switch to param.long0FeesDesired, param.long1FeesDesired, and param.shortFeesDesired and check that the msg.sender has enough fees to be transferred.

OR

Place line 193 after line 199, which does the check and mutates (long0Fees, long1Fees, shortFees) for you

#0 - c4-judge

2023-02-01T09:49:27Z

Picodes marked the issue as duplicate of #121

#1 - c4-judge

2023-02-12T22:27:34Z

Picodes changed the severity to 3 (High Risk)

#2 - c4-judge

2023-02-12T22:27:40Z

Picodes marked the issue as satisfactory

Awards

48.5424 USDC - $48.54

Labels

bug
G (Gas Optimization)
grade-b
G-16

External Links

Gas Findings

[GAS-1] ReentrancyGuard: Consider deprecating NOT_INTERACTED and changeInteractedIfNecessary

Consider deprecating checking for NOT_INTERACTED in ReentrancyGuard.check since actions such as mint/burn that require ReentrancyGuard.check() will revert due to division by zero or underflows and collecting fees would collect 0 if nothing was minted in the first place.

Places that use ReentrancyGuard.check and what stops it from being necessary

ContractFunctionReason
TimeswapV2PoolcollectProtocolFees()Would collect 0 fees
TimeswapV2PoolcollectTransactionFees()Would collect 0 fees
TimeswapV2Poolmint()Reverts on divide by 0 here (pool.sqrtInterestRate is 0)
TimeswapV2Poolburn()Reverts on hasLiquidity()
TimeswapV2Pooldeleverage()Reverts on hasLiquidity()
TimeswapV2Poolleverage()Reverts on hasLiquidity()
TimeswapV2Poolrebalance()Reverts on hasLiquidity()
TimeswapV2LiquidityTokenmint()changeInteractedIfNecessary() in the line right before, which means minting without needing interaction is intended behaviour
TimeswapV2LiquidityTokenburn()Reverts on underflow
TimeswapV2LiquidityTokencollect()Transfers 0 fees even if collect() is properly implemented ([M-1] TimeswapV2LiquidityToken: collect() will always revert because it uses the wrong paramenters when calling ITimeswapV2Pool.transferFees())
TimeswapV2Tokenmint()changeInteractedIfNecessary() in the line right before, which means minting without needing interaction is intended behaviour
TimeswapV2Tokenburn()Reverts on underflow

Recommendation

Consider deprecating checking for NOT_INTERACTED in ReentrancyGuard.check and changeInteractedIfNecessary.

https://github.com/code-423n4/2023-01-timeswap/blob/ef4c84fb8535aad8abd6b67cc45d994337ec4514/packages/v2-pool/src/libraries/ReentrancyGuard.sol#L24

[GAS-2] PoolLibrary: Consider putting pool.xProtocolFees into memory before comparison in collectProtocolFees()

Putting pool.xProtocolFees in memory before the if statement for the 3 types of fees can save gas on SLOADing the same slot multiple times.

Recommendation

Consider putting pool.xProtocolFees into memory before comparison in collectProtocolFees()

https://github.com/code-423n4/2023-01-timeswap/blob/ef4c84fb8535aad8abd6b67cc45d994337ec4514/packages/v2-pool/src/structs/Pool.sol#L226

#0 - c4-judge

2023-02-02T12:29:06Z

Picodes marked the issue as grade-b

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