The attack capitalized on a “reentrancy” bug, much like the one exploited in The DAO. The attacker created a malicious contract masquerading as an ERC20 token, where the “transfer” function called back into the payment channel contract multiple times, draining some ETH each time.
The malicious contract first called createChannel to set up the channel, then called LCOpenTimeout repeatedly via reentrancy. The LCOpenTimeout is there to allow users to quickly exit payment channels which have not yet been joined by the counter-party.
The LCOpenTimeout transfers the user their initial ETH deposit balance and their token deposit balance, both initially set in the createChannel function. Critically, the LCOpenTimeout function only deletes the on-chain channel data (which zeroes out channel balances) after the token transfer function. This allows the malicious contract’s transfer function to call LCOpenTimeout in a loop, each time sending the attacker ETH equivalent to their channel balance. Vector: BVSS:1.1/B:S/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H/CI:N/II:H/AI:N