* The protocol allows users to deposit collateral tokens (WETH/WBTC) and redeem them. When depositing, the contract updates the user's collateral balance before transferring tokens. When redeeming, the contract updates the user's collateral balance before transferring tokens out.
* The `_deposit_collateral()` and `_redeem_collateral()` functions update state variables before making external calls to ERC20 tokens. This violates the Checks-Effects-Interactions pattern and creates a reentrancy vulnerability where malicious ERC20 tokens can reenter the contract during transfer operations and exploit the updated state.
```vyper
@internal
def _deposit_collateral(
token_collateral_address: address, amount_collateral: uint256
):
assert amount_collateral > 0, "DSCEngine_NeedsMoreThanZero"
assert self.token_address_to_price_feed[token_collateral_address] != empty(
address
), "DSCEngine__TokenNotAllowed"
self.user_to_token_address_to_amount_deposited[msg.sender][
token_collateral_address
] += amount_collateral // @> State updated BEFORE external call
log CollateralDeposited(msg.sender, amount_collateral)
success: bool = extcall IERC20(token_collateral_address).transferFrom(
msg.sender, self, amount_collateral // @> External call can reenter
)
assert success, "DSCEngine_TransferFailed"
```
```vyper
@internal
def _redeem_collateral(
token_collateral_address: address,
amount_collateral: uint256,
_from: address,
_to: address,
):
self.user_to_token_address_to_amount_deposited[_from][
token_collateral_address
] -= amount_collateral // @> State updated BEFORE external call
log CollateralRedeemed(token_collateral_address, amount_collateral, _from, _to)
success: bool = extcall IERC20(token_collateral_address).transfer(
_to, amount_collateral // @> External call can reenter
)
assert success, "DSCEngine_TransferFailed"
```
Likelihood:
* Malicious ERC20 tokens can implement hooks in `transfer()` and `transferFrom()` that call back into the DSC Engine contract during the transfer operation
* The protocol accepts any ERC20 token that has a price feed configured, and there's no validation that tokens are non-reentrant
Impact:
* Attackers can mint DSC tokens without actually depositing collateral by reentering during `transferFrom()` and using the updated state to pass health factor checks
* Attackers can redeem more collateral than they deposited by reentering during `transfer()` and manipulating state before the transfer completes
* Direct fund loss and protocol insolvency
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.