Reserve contest - wait's results

A permissionless platform to launch and govern asset-backed stable currencies.

General Information

Platform: Code4rena

Start Date: 06/01/2023

Pot Size: $210,500 USDC

Total HM: 27

Participants: 73

Period: 14 days

Judge: 0xean

Total Solo HM: 18

Id: 203

League: ETH

Reserve

Findings Distribution

Researcher Performance

Rank: 8/73

Findings: 2

Award: $4,676.19

🌟 Selected for report: 1

🚀 Solo Findings: 1

Findings Information

🌟 Selected for report: immeas

Also found by: HollaDieWaldfee, JTJabba, hihen, rvierdiiev, unforgiven, wait

Labels

bug
2 (Med Risk)
satisfactory
duplicate-267

Awards

258.0215 USDC - $258.02

External Links

Lines of code

https://github.com/reserve-protocol/protocol/blob/df7ecadc2bae74244ace5e8b39e94bc992903158/contracts/p1/RToken.sol#L186 https://github.com/reserve-protocol/protocol/blob/df7ecadc2bae74244ace5e8b39e94bc992903158/contracts/p1/RToken.sol#L406-L418

Vulnerability details

Impact

The RToken issuance will not work, i.e users will not be able to mint new RTokens.

Proof of Concept

The issuing time of RToken is determined by RToken#allVestAt and issue amount. Every issuance will increase the allVestAt, which will make later issuances to have a bigger issuing time. Therefore, a malicious user can rapidly increase the allVestAt by issuing large issues, which makes all subsequent users have to wait a long time to issue.

Originally, this wouldn't be a big deal, because it requires the malicious user to pledge all the assets to the protocol. But, RToken also has a RToken#cancel() function which allows a user to cancel his pending issuances in the issueQueues at any time without any cost.

Using this, the malicious user can extend the issuance period for all subsequent users quickly and costless by iteratively calling issue() and cancel(). Also because it is costless for calling cancel(), flashloan can be used to improve the efficiency of the attack.

Tools Used

Manual

We can set a wait time for the cancel operation, that larger issuance will need wait more time to cancel.

#0 - c4-judge

2023-01-23T21:20:53Z

0xean marked the issue as duplicate of #364

#1 - c4-judge

2023-01-23T21:20:58Z

0xean marked the issue as satisfactory

Findings Information

🌟 Selected for report: wait

Labels

bug
2 (Med Risk)
downgraded by judge
satisfactory
selected for report
M-15

Awards

4418.1679 USDC - $4,418.17

External Links

Lines of code

https://github.com/reserve-protocol/protocol/blob/df7ecadc2bae74244ace5e8b39e94bc992903158/contracts/p1/Furnace.sol#L70-L84

Vulnerability details

Impact

Malicious users can get more of the RToken appreciation benefit brought by Furnace.sol#melt(), and long-term RToken holders will get less benefit. RToken holders will be less willing to provide liquidity to RToken pools (such as uniswap pools), resulting in less liquidity of RToken.

Proof of Concept

A1. Gain revenue from a flashloan sandwich attack

A malicious user can launch a flashloan sandwich attack against Furnace#melt() each time a whole period passed (payout happens).

The attack transaction execution steps:

  1. Borrow some assets (inputFund) with a flashloan
  2. Swap the inputFund for RToken
  3. Call RToken#redeem() to change the RToken to basket assets(outputFund). The redeem() will invoke Furnace.melt() automatically.
  4. Swap part of outputFund for inputFund and pay back the flashloan, the rest of outputFund is the profit.

The implicit assumption here is that most of the time the prices of RToken in RToken.issues(), RToken.redeem(), and DeFi pools are almost equal. This assumption is reasonable because if there are price differentials, they can be balanced by arbitrage.

The attack can be profitable for:

  • Furnace#melt() will increase the price of RToken in issue/redeem (according to basket rate).
  • Step 2 buys RTokens at a lower price, and then step 3 sells RTokens at a higher price(melt() is called first in redeem()).

A2. Get a higher yield by holding RToken for a short period of time

Malicious users can get higher yield by by following these steps:

  1. Calculate the next payout block of Furnace in advance
  2. Call RToken#issue() 1 to n blocks before the payout block
  3. Call RToken#redeem() when the payout block reaches.

Since this approach only requires 1 to n blocks to issue in advance, which is typically much smaller than rewardPeriod, the attacker will obtain much higher APR than long-term RToken holders.

Tools Used

Manual

Referring to eip-4626, distribute rewards based on time weighted shares.

Alternatively, always use a very small rewardPeriod and rewardRatio, and lower the upper limit MAX_RATIO and MAX_PERIOD.

#0 - c4-judge

2023-01-23T19:15:07Z

0xean changed the severity to 2 (Med Risk)

#1 - c4-judge

2023-01-23T23:35:49Z

0xean marked the issue as satisfactory

#2 - tbrent

2023-01-26T00:43:07Z

Agreed with the warden. And agree this is a Medium severity issue.

(aside: we are already planning to fix the period at 12s to mitigate this issue)

#3 - tbrent

2023-02-07T23:19:12Z

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