The WJLP.wrap function accepts a from parameter and a to parameter.
The tokens are transferred from the from account to the to account:
function wrap(uint _amount, address _from, address _to, address _rewardOwner) external override {
// @audit can frontrun and steal => use from=victim, to=attacker
JLP.transferFrom(_from, address(this), _amount);
JLP.approve(address(_MasterChefJoe), _amount);
// stake LP tokens in Trader Joe's.
// In process of depositing, all this contract's
// accumulated JOE rewards are sent into this contract
_MasterChefJoe.deposit(_poolPid, _amount);
// update user reward tracking
_userUpdate(_rewardOwner, _amount, true);
_mint(_to, _amount);
}
When a user wants to wrap their JLP tokens, they first need to approve the contracts with their token and in a second transaction call the wrap function.
However, an attacker can frontrun the actual wrap function and call their own wrap(from=victim, to=attacker) which will make the victim pay with their approved tokens but the WJLP are minted to the attacker.
Impact
WJLP tokens can be stolen.
Recommended Mitigation Steps
Always transfer from msg.sender instead of using a caller-provided from parameter.
Handle
cmichel
Vulnerability details
The
WJLP.wrap
function accepts afrom
parameter and ato
parameter. The tokens are transferred from thefrom
account to theto
account:When a user wants to wrap their JLP tokens, they first need to approve the contracts with their token and in a second transaction call the
wrap
function. However, an attacker can frontrun the actualwrap
function and call their ownwrap(from=victim, to=attacker)
which will make the victim pay with their approved tokens but the WJLP are minted to the attacker.Impact
WJLP tokens can be stolen.
Recommended Mitigation Steps
Always transfer from
msg.sender
instead of using a caller-providedfrom
parameter.