20,000 USDC
View results
Submission Details
Severity: high

Anyone can drain contract tokens by the setPool() function

Summary

Anyone can drain contract tokens by the setPool() function. this function is used to create or update pool info by lenders but the issue is function logic for transferring loanToken can lead to draining whole contract tokens by attacker.

Vulnerability Details

setPool() function checks the difference between the p.poolBalance and currentBalance of the pool and tries to transfer tokens to reach out currentBalance.

if (p.poolBalance > currentBalance) {
// if new balance > current balance then transfer the difference from the lender
IERC20(p.loanToken).transferFrom(
p.lender,
address(this),
p.poolBalance - currentBalance
);
} else if (p.poolBalance < currentBalance) {
// if new balance < current balance then transfer the difference back to the lender
IERC20(p.loanToken).transfer(
p.lender,
currentBalance - p.poolBalance
);
}

in this scenario attacker be able to drain vault:

  • attacker creates a pool with 100 DAI token as loanToken.

  • calls the setPool() function again to update pool info.

  • set loanToken to WETH and set p.poolBalance to 1 WETH.

  • function store currentBalance with uint256 currentBalance = pools[poolId].poolBalance; so currentBalance should 100 DAI.

  • because of current balance is more than the pool balance, function continues with this:

else if (p.poolBalance < currentBalance) {
// if new balance < current balance then transfer the difference back to the lender
IERC20(p.loanToken).transfer(
p.lender,
currentBalance - p.poolBalance
);
}
  • function transfers the difference between currentBalance and p.poolBalance to the lender.

  • so we have: (100000000000000000000 - 1000000000000000000) Note: DAI and WETH is 18 decimal

  • as a result, the function transfers 99 WETH from the contract to the attacker. because p.loanToken is WETH.

Impact

Attacker can steal contract tokens by the setPool() function.

Tools Used

Manual Review

Recommendations

  • Consider whitelisting tokens or changing the implementation of the setPool() function to avoid this issue.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.