0 _amount is not checked in mint function which can make a user steal EUROs.
There is no protection against reentrancy in the mint function. And the function doesn't check if the "_to" address is a contract. Also, there is no restriction against having 0 amount.
A malicious user can:
Deposit collateral in the vault
Mint a large number of EUROs at the first call of the mint function
Reenter the mint function and mint 0 amount this time
Both "fee" and "minted" would be 0 because the reentrancy would have overwritten the first call.
Call any of the removeCollateral functions (depending on the collateral deposited) to remove collateral.
Here's the design of the mint function:
function mint(address _to, uint256 _amount) external onlyOwner ifNotLiquidated {
uint256 fee = _amount * ISmartVaultManagerV3(manager).mintFeeRate() / ISmartVaultManagerV3(manager).HUNDRED_PC();
require(fullyCollateralised(_amount + fee), UNDER_COLL);
minted = minted + _amount + fee;
EUROs.mint(_to, _amount);
EUROs.mint(ISmartVaultManagerV3(manager).protocol(), fee);
emit EUROsMinted(_to, _amount, fee);
}
Had it been that EUROs.mint(ISmartVaultManagerV3(manager).protocol(), fee) comes before EUROs.mint(_to, _amount), this attack wouldn't have been totally possible. This is because, the malicious user would have paid the appropriate fee for his fist mint to the protocol before minting for himself.
However, once the function gets to this line: EUROs.mint(_to, _amount), the malicious user will reenter the function and overwrite the first transaction.
A user can steal EUROs.
Manual review
I suggest using a reentrancy guard and check against minting 0 amount.
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.