Submitted by kirk-baird, also found by hyh, rayn, TomFrenchBlockchain, VAD37, WatchPug, and wuwe1
LibSwap.sol#L42
Swapper.sol#L12-L23
msg.value is attached multiple times to external swap calls in LibSwap.swap().
If Swapper._executeSwaps() is called with the native token as the swapData.fromAssetId more than once and msg.value > 0 then more value will be transferred out of the contract than is received since msg.value will be transferred out _swapData.length times.
The impact is that the contract can have all the native token balance drained by an attacker who has makes repeated swap calls from the native token into any other ERC20 token. Each time the original msg.value of the sender will be swapped out of the contract. This attack essentially gives the attacker _swapData.length * msg.value worth of native tokens (swapped into another ERC20) when they should only get msg.value.
Swapper._executeSwaps() iterates over a list of  SwapData calling LibSwap.swap() each time (note this is an internal call).
Inside LibSwap.swap() we make an external call to _swapData.callTo with value : msg.value. Due to the loop in Swapper._executeSwaps() this repeatedly sends the original msg.value in the external call.
This issue may be mitigated by only allowing fromAssetId to be the native token once in _swapData in Swapper._executeSwaps(). If it occurs more than once the transaction should revert.
H3xept (Li.Fi) acknowledged, but disagreed with High severity and commented:
gzeon (judge) decreased severity to Medium and commented:
ezynda3 (Li.Fi) resolved and commented:
