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
Rank: 8/73
Findings: 2
Award: $4,676.19
🌟 Selected for report: 1
🚀 Solo Findings: 1
🌟 Selected for report: immeas
Also found by: HollaDieWaldfee, JTJabba, hihen, rvierdiiev, unforgiven, wait
258.0215 USDC - $258.02
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
The RToken issuance will not work, i.e users will not be able to mint new RTokens.
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.
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
🌟 Selected for report: wait
4418.1679 USDC - $4,418.17
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.
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:
inputFund
) with a flashloaninputFund
for RTokenoutputFund
). The redeem()
will invoke Furnace.melt()
automatically.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).melt()
is called first in redeem()
).Malicious users can get higher yield by by following these steps:
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.
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
Addressed here: https://github.com/reserve-protocol/protocol/pull/571