Anyone can exchange ETH for any token in the pool at a ratio of 1:1
Proof of Concept
The main logic of withdrawLPTokens function in GiantPoolBase is:
// Burn giant LP from user before sending them an LP token from this pool
lpTokenETH.burn(msg.sender, amount);
// Giant LP tokens in this pool are 1:1 exchangeable with external savETH vault LP
token.transfer(msg.sender, amount);
The function doesn't check what the token passed in is, and calls token.transfer(msg.sender, amount); directly after eth lp is burnt.
If there is a token T with higher price than eth in the pool, then an attacker can pass in the address of the token T as a lpToken to swap ETH for T.
Tools Used
n/a
Recommended Mitigation Steps
Register all LPTokens in a global trusted contract (e.g. LSDNFactory - liquidStakingDerivativeFactory), and check the passed in lpToken addresses in the registry.
Lines of code
https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/GiantPoolBase.sol#L69-L90
Vulnerability details
Impact
Anyone can exchange ETH for any token in the pool at a ratio of 1:1
Proof of Concept
The main logic of withdrawLPTokens function in GiantPoolBase is:
The function doesn't check what the token passed in is, and calls
token.transfer(msg.sender, amount);
directly after eth lp is burnt.If there is a token T with higher price than eth in the pool, then an attacker can pass in the address of the token T as a lpToken to swap ETH for T.
Tools Used
n/a
Recommended Mitigation Steps
Register all LPTokens in a global trusted contract (e.g. LSDNFactory - liquidStakingDerivativeFactory), and check the passed in lpToken addresses in the registry.