Skip to content

Commit

Permalink
feat(axelarnet)!: refund from escrow address to IBC account (#2202)
Browse files Browse the repository at this point in the history
  • Loading branch information
haiyizxx authored Oct 29, 2024
1 parent e122d6e commit fe8587a
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 3 deletions.
32 changes: 29 additions & 3 deletions x/axelarnet/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ func (m AxelarnetIBCModule) OnAcknowledgementPacket(
return err
}

return m.setRoutedPacketFailed(ctx, packet)
return m.setRoutedPacketFailed(ctx, packet, m.bank)
}
}

Expand All @@ -287,7 +287,7 @@ func (m AxelarnetIBCModule) OnTimeoutPacket(
return err
}

return m.setRoutedPacketFailed(ctx, packet)
return m.setRoutedPacketFailed(ctx, packet, m.bank)
}

// returns the transfer id and delete the existing mapping
Expand Down Expand Up @@ -334,7 +334,7 @@ func setRoutedPacketCompleted(ctx sdk.Context, k keeper.Keeper, n types.Nexus, p
return nil
}

func (m AxelarnetIBCModule) setRoutedPacketFailed(ctx sdk.Context, packet channeltypes.Packet) error {
func (m AxelarnetIBCModule) setRoutedPacketFailed(ctx sdk.Context, packet channeltypes.Packet, bank types.BankKeeper) error {
// IBC ack/timeout packets, by convention, use the source port/channel to represent native chain -> counterparty chain channel id
// https://github.com/cosmos/ibc/tree/main/spec/core/ics-004-channel-and-packet-semantics#definitions
port, channel, sequence := packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()
Expand All @@ -347,6 +347,11 @@ func (m AxelarnetIBCModule) setRoutedPacketFailed(ctx sdk.Context, packet channe
return err
}

err = refundFromAssetEscrowAddressToIBCAccount(ctx, packet, bank)
if err != nil {
return err
}

err = lockableAsset.LockFrom(ctx, types.AxelarIBCAccount)
if err != nil {
return err
Expand Down Expand Up @@ -395,3 +400,24 @@ func extractTokenFromAckOrTimeoutPacket(packet channeltypes.Packet) sdk.Coin {

return sdk.NewCoin(trace.IBCDenom(), amount)
}

// Temporary logic to handle in-transit IBC transfers during upgrade. Previously IBC transfers were sent from the asset
// escrow address, but now they're sent from Axelar IBC account. IBC refunds the token to the original sender, so we move
// the tokens from the asset escrow to the Axelar IBC account for correct processing.
//
// Deprecated: Remove this function after the v1.1 upgrade and ensure no in-transit IBC transfers are left.
func refundFromAssetEscrowAddressToIBCAccount(ctx sdk.Context, packet channeltypes.Packet, bank types.BankKeeper) error {
// Packet is validated by the IBC module, so we can safely assume it's a valid ICS20 packet
data := funcs.Must(types.ToICS20Packet(packet))

originalSender := funcs.Must(sdk.AccAddressFromBech32(data.Sender))
if originalSender.Equals(types.AxelarIBCAccount) {
return nil
}

denom := ibctransfertypes.ParseDenomTrace(data.Denom).IBCDenom()
transferAmount := funcs.MustOk(sdk.NewIntFromString(data.Amount))

token := sdk.NewCoin(denom, transferAmount)
return bank.SendCoins(ctx, originalSender, types.AxelarIBCAccount, sdk.NewCoins(token))
}
16 changes: 16 additions & 0 deletions x/axelarnet/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ func TestIBCModule(t *testing.T) {
transfer := funcs.MustOk(k.GetTransfer(ctx, transfer.ID))
assert.Equal(t, types.TransferFailed, transfer.Status)
assert.Len(t, lockableAsset.LockFromCalls(), 1)
assert.Len(t, bankK.SendCoinsCalls(), 2)
}),

whenPendingTransfersExist.
Expand Down Expand Up @@ -237,5 +238,20 @@ func TestIBCModule(t *testing.T) {
assert.Equal(t, nexus.Failed, message.Status)
assert.Len(t, lockableAsset.LockFromCalls(), 1)
}),

seqMapsToID.
When2(whenChainIsActivated).
When("lock coin succeeds", lockCoin(true)).
When("packet sender is from IBC account", func() {
fungibleTokenPacket.Sender = types.AxelarIBCAccount.String()
packet = channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), packetSeq, ibctransfertypes.PortID, channelID, ibctransfertypes.PortID, channelID, clienttypes.NewHeight(0, 110), 0)
}).
When2(whenOnTimeout).
Then("should not trigger refund from asset escrow to IBC account", func(t *testing.T) {
transfer := funcs.MustOk(k.GetTransfer(ctx, transfer.ID))
assert.Equal(t, types.TransferFailed, transfer.Status)
assert.Len(t, lockableAsset.LockFromCalls(), 1)
assert.Len(t, bankK.SendCoinsCalls(), 1)
}),
).Run(t)
}

0 comments on commit fe8587a

Please sign in to comment.