Open code423n4 opened 2 years ago
Bridge functions are vulnerable aswell.
Fixed in lifinance/lifi-contracts@703919f74d8b750e3bcf7a84bdcb4d742bc8d45a
Sponsor confirmed with fix. While the reentrancy is valid there are no exploit, keeping this and all duplicates as Med Risk.
Lines of code
https://github.com/code-423n4/2022-03-lifinance/blob/699c2305fcfb6fe8862b75b26d1d8a2f46a551e6/src/Facets/DiamondCutFacet.sol#L14-L22 https://github.com/code-423n4/2022-03-lifinance/blob/699c2305fcfb6fe8862b75b26d1d8a2f46a551e6/src/Facets/CBridgeFacet.sol#L92-L121 https://github.com/code-423n4/2022-03-lifinance/blob/699c2305fcfb6fe8862b75b26d1d8a2f46a551e6/src/Facets/AnyswapFacet.sol#L74-L110 https://github.com/code-423n4/2022-03-lifinance/blob/699c2305fcfb6fe8862b75b26d1d8a2f46a551e6/src/Facets/NXTPFacet.sol#L85-L102 https://github.com/code-423n4/2022-03-lifinance/blob/699c2305fcfb6fe8862b75b26d1d8a2f46a551e6/src/Facets/NXTPFacet.sol#L150-L171
Vulnerability details
Impact
There is a reenterancy vulnerability in functions which call
Swapper._executeSwap()
which would allow the attacker to change theirpostSwapBalance
.The functions following similar logic to that seen in
GenericSwapFacet.swapTokensGeneric()
.This logic records the balance before and after the
_executeSwaps()
function. The difference is then transferred to themsg.sender
.The issue occurs since it is possible for an attacker to reenter this function during
_executeSwaps()
, that is because execute swap makes numerous external calls, such as to the AMM, or to untrusted ERC20 token addresses.If a function is called such as
WithdrawFacet.withdraw()
this will impact the calculations ofpostSwapBalance
which will account for the funds transferred out during withdrawal. Furthermore, any functions which transfers funds into the contract will also be counted in thepostSwapBalance
calculations.Vulnerable Functions:
GenericSwapFacet.swapTokensGeneric()
CBridgeFacet.swapAndStartBridgeTokensViaCBridge()
AnyswapFacet.swapAndStartBridgeTokensViaAnyswap()
HopFacet.swapAndStartBridgeTokensViaHop()
NXTPFacet.swapAndStartBridgeTokensViaNXTP()
NXTPFacet.swapAndCompleteBridgeTokensViaNXTP()
Proof of Concept
GenericSwapFacet.swapTokensGeneric()
CBridgeFacet.swapAndStartBridgeTokensViaCBridge()
AnyswapFacet.swapAndStartBridgeTokensViaAnyswap()
HopFacet.swapAndStartBridgeTokensViaHop()
NXTPFacet.swapAndStartBridgeTokensViaNXTP()
NXTPFacet.swapAndCompleteBridgeTokensViaNXTP()
Recommended Mitigation Steps
Consider adding a reentrancy guard over every function which may send or receive tokens. It may be easiest too add this guard over the
fallback()
function however that could prevent view functions from being called (since it would perform storage operations).Ensure the same slot is used to store the reentrancy guard so all required functions are covered by a single guard.