The StabilityPool's exchange rate mechanism fails to account for the relationship between RToken
and DEToken
balances, leading to incorrect token distributions during withdrawals. This creates a fundamental pricing mismatch that could be exploited to extract excess value from the protocol.
The exchange rate is hardcoded to 1e18
, meaning 1 DEToken always equals 1 RToken regardless of actual pool conditions. But this ignores basic economic principles where token ratios should float based on supply and demand within the pool. The vulnerability flows through both functions, with getExchangeRate()
providing an incorrect fixed rate that withdraw()
then uses to calculate token amounts,
Attack Flow A user deposits DETokens into the StabilityPool. Later, when withdrawing, they receive RTokens at a 1:1 ratio even if the pool's actual RToken backing has decreased due to liquidations or other factors. This fixed rate allows users to withdraw more RTokens than they should rightfully receive based on pool conditions.
The StabilityPool's exchange rate mechanism reveals a flaw in how RToken
and DEToken
conversions are handled. Imagine a bank offering to exchange dollars for euros at exactly 1:1 regardless of market conditions this is effectively what the StabilityPool does with its tokens.
Let's walk through how this plays out:
When users interact with the StabilityPool, they deposit DETokens expecting fair representation of their share in the RToken
reserves. However, the getExchangeRate()
function in StabilityPool.sol returns a fixed 1e18
value, treating these tokens as perpetually equivalent regardless of market dynamics or pool conditions.
The real-world impact becomes clear when we examine the withdrawal process. A user who deposited 1000 DETokens when the pool was healthy can withdraw 1000 RTokens even after significant liquidations have reduced the pool's RToken
backing. This creates a 'first-out' advantage where early withdrawers receive full value while later users find themselves holding DETokens backed by depleted reserves.
Looking at the numbers:
This fixed rate ignores the fundamental principle that token ratios should reflect the pool's actual reserves, currently sitting at rToken.balanceOf(address(this))
RTokens backing deToken.totalSupply()
DETokens.
The fixed exchange rate prevents proper price discovery between RToken and DEToken, potentially allowing users to withdraw more RTokens than they should receive based on pool conditions.
Implement proper exchange rate calculation
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.