The depositRAACFromPool()
function in the RAACMinter
contract is susceptible to a race condition that can lead to incorrect balance checks and potential reverts. This occurs when an immediate call to any function that invokes _update()
in the StabilityPool
contract that can modify the balance of RAAC tokens
between the time the balance is checked and the time the transfer is executed.
The depositRAACFromPool()
function does not update RAAC tokens
balance in StabilityPool
prior to adding more tokens:
The function simply takes a snapshot of the current raacToken balance (preBalance
), proceeds to transfer more tokens to the contract and then performs a check between the final balance after transfer (postBalance
) and the initial balance.
However, this will result in revert
if another function that invokes _update()
is called immediately and is executed fully before this one is completed.
Logic:
The _update()
function calls _mintRAACRewards()
which calls raacMinter.tick()
that performs the following:
Now, in ethereum blockchain, transactions are not always executed sequentially by the order of their initiation. This means that any transaction can be executed earlier than one that was initiated before it.
Initial State:
The StabilityPool
has 1000 RAAC tokens
.
depositRAACFromPool(200 RAAC tokens)
is then called from liquidity pool.
Checking the balance, (preBalance = 1000 RAAC tokens
).
Another Action:
Immediately after, Bob
calls deposit()
on the StabilityPool
, triggering _update()
and minting 500 RAAC tokens
.
This transaction is executed and the StabilityPool
balance is now updated to 1500 RAAC tokens
.
3.Initial Transfer proceeds:
The depositRAACFromPool()
proceeds to transfer 200 RAAC tokens
, resulting in a new balance of 1700 RAAC tokens
(1500 + 200
).
The check if (postBalance != preBalance + amount)
evaluates to if (1700 != 1000 + 200)
, which therefore fails.
This race condition therefore leads to the depositRAACFromPool()
function reverting due to an incorrect balance check, potentially disrupting the expected flow of token deposits and affecting user experience.
Manual Review
Invoke the _update()
function within depositRAACFromPool()
before performing the transfer.
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.