The issue() and issueTo() functions allow users to mint new RTokens by depositing the required collateral baskets. The contract tracks the number of collateral baskets needed (basketsNeeded) to fully collateralize the RToken supply and calculates the exchange rate as basketsNeeded / totalSupply.
There is an issue in the _scaleUp() function, which is called by issueTo() to mint new tokens and update the basketsNeeded value. The problem arises when minting tokens from a zero supply state. In this case, the function mints amtBaskets worth of RTokens instead of using the current exchange rate, allowing the effective exchange rate to decrease on subsequent mints.
Impact
Minting more RTokens than intended for the deposited collateral, leading to an inflated supply and insufficient collateral backing.
Incorrect accounting of collateral and RTokens in the system, potentially causing solvency issues for the protocol.
Proof of Concept
The RToken contract is deployed with an initial zero supply and zero basketsNeeded.
Alice calls issueTo(alice, 1), minting 1 RToken to her address. The _scaleUp() function is called with amtBaskets = 1, totalSupply = 0, and basketsNeeded = 0. Since totalSupply is zero, the function mints amtRToken = amtBaskets = 1 to Alice and updates basketsNeeded to 1.
Bob calls issueTo(bob, 1), minting 1 RToken to his address. The _scaleUp() function is called with amtBaskets = 1, totalSupply = 1, and basketsNeeded = 1. The function calculates amtRToken as follows:
Lines of code
https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/RToken.sol#L483-L497 https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/RToken.sol#L89-L110
Vulnerability details
The
issue()
andissueTo()
functions allow users to mint new RTokens by depositing the required collateral baskets. The contract tracks the number of collateral baskets needed (basketsNeeded
) to fully collateralize the RToken supply and calculates the exchange rate asbasketsNeeded / totalSupply
.There is an issue in the
_scaleUp()
function, which is called byissueTo()
to mint new tokens and update thebasketsNeeded
value. The problem arises when minting tokens from a zero supply state. In this case, the function mintsamtBaskets
worth of RTokens instead of using the current exchange rate, allowing the effective exchange rate to decrease on subsequent mints.Impact
Proof of Concept
The RToken contract is deployed with an initial zero supply and zero
basketsNeeded
.Alice calls
issueTo(alice, 1)
, minting 1 RToken to her address. The_scaleUp()
function is called withamtBaskets = 1
,totalSupply = 0
, andbasketsNeeded = 0
. SincetotalSupply
is zero, the function mintsamtRToken = amtBaskets = 1
to Alice and updatesbasketsNeeded
to 1.Bob calls
issueTo(bob, 1)
, minting 1 RToken to his address. The_scaleUp()
function is called withamtBaskets = 1
,totalSupply = 1
, andbasketsNeeded = 1
. The function calculatesamtRToken
as follows:This results in
amtRToken = 1 * 1 / 1 = 1
, minting 1 RToken to Bob and updatingbasketsNeeded
to 2.The exchange rate has decreased from 1 basket per RToken (after Alice's mint) to 0.5 baskets per RToken (after Bob's mint).
Tools Used
Manual review
Recommended Mitigation Steps
The
_scaleUp()
function should establish a non-zero initialbasketsNeeded
value when minting from a zero supply state.Assessed type
Math