IF IBC 06
IF-IBC-06
ICS20 - Specification allows token lost issue in the crossing hellos scenario
Severity: High
Type: Specification error
Difficulty: easy
Involved artifacts: ICS 20, applications/transfer/module.go
Description
The ICS20 specification uses undefined newAddress() in onChanOpenInit and
onChanOpenTry to create an escrow address and stores it in a map under the channel id as a key. In the case of
crossing-hello scenario, different escrow accounts are created both in onChanOpenInit and onChanOpenTry, with
latter overwriting the former. This can lead to the token lost issue if createOutgoingPacket is called in
between.
Problem Scenarios
Imagine the following scenario:
-
on chain A
onChanOpenInitis called which leads to the creation of the escrow addressE1that is stored inchannelEscrowAddressesunderchannelIdentifieras a key -
on chain A,
createOutgoingPacketis called, and it moves tokens to the escrow addressE1 -
on chain A,
onChanOpenTryis called that creates a new escrow addressE2that replacesE1in thechannelEscrowAddressesmap underchannelIdentifieras a key. -
on chain A,
onRecvPacketis called to withdraw tokens that are escrowed inE1withcreateOutgoingPacket. It will fail as there are no tokens in the escrow accountchannelEscrowAddresses[channelIdentifier]as it points toE2, while tokens are inE1.
Recommendation
In onChanOpenTry, the escrow account should be created only if it does not exist, i.e.,
a check should be added to create an escrow account only if channelEscrowAddresses[channelIdentifier]
does not exist.
Note that the in the SDK implementation of the ICS20, code uses a deterministic function
to create an escrow account that receives two parameters portId and channelId. Therefore,
this implementation does not suffer from the problem mentioned here as the implementation differ
from the specification, i.e., only one escrow account is created in the mentioned scenario.