Unwanted deposits and withdrawals can be triggered on behalf of another user
Description
The deposit() and withdraw() functions of the Vault contract accept two arguments:
function deposit(uint256 amountIn, address receiver)
public
override
nonReentrant
ensureFeesAreCollected
returns (uint256 shares)
{
/// checks for only batcher deposit
onlyBatcher();
...
}
function withdraw(uint256 sharesIn, address receiver)
public
override
nonReentrant
ensureFeesAreCollected
returns (uint256 amountOut)
{
/// checks for only batcher withdrawal
onlyBatcher();
...
}Both of the functions call onlyBatcher() to check and enforce the validity of msg.sender:
function onlyBatcher() internal view {
if (batcherOnlyDeposit) {
require(msg.sender == batcher, "ONLY_BATCHER");
}
}Both of the functions perform no other checks of the validity of msg.sender.
By default (batcherOnlyDeposit = true), only the Batcher contract can deposit and withdraw funds on behalf of the receiver.
The governance can change batcherOnlyDeposit to false. When batcherOnlyDeposit = false, the deposit() and withdraw() functions perform no msg.sender validity checks whatsoever, allowing any third-party user to trigger deposits and withdrawals on behalf of any receiver.
Impact
A third party can trigger unwanted deposits and withdrawals on behalf of another user. This can lead to the users' confusion, lost profits, and even potentially to a loss of funds.
Recommendations
Consider adding if (!batcherOnlyDeposit) { require(msg.sender == receiver); } checks to the deposit() and withdraw() functions.
Remediation
The issue has been fixed in commit 32d30c8↗.