github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/apps/transfer/ibc_module.go (about) 1 package transfer 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 8 types2 "github.com/fibonacci-chain/fbc/libs/tendermint/types" 9 10 porttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/05-port/types" 11 12 sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors" 13 14 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 15 capabilitytypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/capability/types" 16 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/transfer/keeper" 17 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/transfer/types" 18 channeltypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types" 19 host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host" 20 ibcexported "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/exported" 21 ) 22 23 var ( 24 _ porttypes.Middleware = IBCModule{} 25 errNotSupportICS20 = errors.New("not support by ics-20") 26 ) 27 28 // NewIBCModule creates a new IBCModule given the keeper 29 func NewIBCModule(k keeper.Keeper, v2module AppModule) porttypes.Middleware { 30 return IBCModule{ 31 keeper: k, 32 v2Module: v2module, 33 } 34 } 35 36 // OnChanOpenInit implements the IBCModule interface 37 func (im IBCModule) OnChanOpenInit( 38 ctx sdk.Context, 39 order channeltypes.Order, 40 connectionHops []string, 41 portID string, 42 channelID string, 43 chanCap *capabilitytypes.Capability, 44 counterparty channeltypes.Counterparty, 45 version string, 46 ) (string, error) { 47 if !types2.HigherThanVenus4(ctx.BlockHeight()) { 48 return im.v2Module.OnChanOpenInit(ctx, order, connectionHops, portID, channelID, chanCap, counterparty, version) 49 } 50 51 if err := ValidateTransferChannelParamsV4(ctx, im.keeper, order, portID, channelID); err != nil { 52 return "", err 53 } 54 55 if strings.TrimSpace(version) == "" { 56 version = types.Version 57 } 58 59 if version != types.Version { 60 return "", sdkerrors.Wrapf(types.ErrInvalidVersion, "got %s, expected %s", version, types.Version) 61 } 62 63 // Claim channel capability passed back by IBC module 64 if err := im.keeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { 65 return "", err 66 } 67 68 return version, nil 69 } 70 71 // OnChanOpenTry implements the IBCModule interface. 72 func (im IBCModule) OnChanOpenTry( 73 ctx sdk.Context, 74 order channeltypes.Order, 75 connectionHops []string, 76 portID, 77 channelID string, 78 chanCap *capabilitytypes.Capability, 79 counterparty channeltypes.Counterparty, 80 version string, 81 counterpartyVersion string, 82 ) (string, error) { 83 if !types2.HigherThanVenus4(ctx.BlockHeight()) { 84 return im.v2Module.OnChanOpenTry(ctx, order, connectionHops, portID, channelID, chanCap, counterparty, version, counterpartyVersion) 85 } 86 87 if err := ValidateTransferChannelParamsV4(ctx, im.keeper, order, portID, channelID); err != nil { 88 return "", err 89 } 90 91 if counterpartyVersion != types.Version { 92 return "", sdkerrors.Wrapf(types.ErrInvalidVersion, "invalid counterparty version: got: %s, expected %s", counterpartyVersion, types.Version) 93 } 94 95 // OpenTry must claim the channelCapability that IBC passes into the callback 96 if err := im.keeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { 97 return "", err 98 } 99 100 return types.Version, nil 101 } 102 103 // OnChanOpenAck implements the IBCModule interface 104 func (im IBCModule) OnChanOpenAck( 105 ctx sdk.Context, 106 portID, 107 channelID string, 108 _ string, 109 counterpartyVersion string, 110 ) error { 111 if counterpartyVersion != types.Version { 112 return sdkerrors.Wrapf(types.ErrInvalidVersion, "invalid counterparty version: %s, expected %s", counterpartyVersion, types.Version) 113 } 114 return nil 115 } 116 117 // OnChanOpenConfirm implements the IBCModule interface 118 func (im IBCModule) OnChanOpenConfirm( 119 ctx sdk.Context, 120 portID, 121 channelID string, 122 ) error { 123 return nil 124 } 125 126 // OnChanCloseInit implements the IBCModule interface 127 func (im IBCModule) OnChanCloseInit( 128 ctx sdk.Context, 129 portID, 130 channelID string, 131 ) error { 132 // Disallow user-initiated channel closing for transfer channels 133 return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "user cannot close channel") 134 } 135 136 // OnChanCloseConfirm implements the IBCModule interface 137 func (im IBCModule) OnChanCloseConfirm( 138 ctx sdk.Context, 139 portID, 140 channelID string, 141 ) error { 142 return nil 143 } 144 145 // OnRecvPacket implements the IBCModule interface. A successful acknowledgement 146 // is returned if the packet data is successfully decoded and the receive application 147 // logic returns without error. 148 func (im IBCModule) OnRecvPacket( 149 ctx sdk.Context, 150 packet channeltypes.Packet, 151 relayer sdk.AccAddress, 152 ) ibcexported.Acknowledgement { 153 if !types2.HigherThanVenus4(ctx.BlockHeight()) { 154 return im.v2Module.OnRecvPacket(ctx, packet, relayer) 155 } 156 157 ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) 158 159 var data types.FungibleTokenPacketData 160 var ackErr error 161 if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { 162 ackErr = sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "cannot unmarshal ICS-20 transfer packet data") 163 ack = channeltypes.NewErrorAcknowledgementV4(ackErr) 164 } 165 166 // only attempt the application logic if the packet data 167 // was successfully decoded 168 if ack.Success() { 169 err := im.keeper.OnRecvPacket(ctx, packet, data) 170 if err != nil { 171 ack = channeltypes.NewErrorAcknowledgementV4(err) 172 ackErr = err 173 } 174 } 175 176 eventAttributes := []sdk.Attribute{ 177 sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), 178 sdk.NewAttribute(sdk.AttributeKeySender, data.Sender), 179 sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), 180 sdk.NewAttribute(types.AttributeKeyDenom, data.Denom), 181 sdk.NewAttribute(types.AttributeKeyAmount, data.Amount), 182 sdk.NewAttribute(types.AttributeKeyAckSuccess, fmt.Sprintf("%t", ack.Success())), 183 } 184 185 if ackErr != nil { 186 eventAttributes = append(eventAttributes, sdk.NewAttribute(types.AttributeKeyAckError, ackErr.Error())) 187 } 188 189 ctx.EventManager().EmitEvent( 190 sdk.NewEvent( 191 types.EventTypePacket, 192 eventAttributes..., 193 ), 194 ) 195 196 // NOTE: acknowledgement will be written synchronously during IBC handler execution. 197 return ack 198 } 199 200 // OnAcknowledgementPacket implements the IBCModule interface 201 func (im IBCModule) OnAcknowledgementPacket( 202 ctx sdk.Context, 203 packet channeltypes.Packet, 204 acknowledgement []byte, 205 relayer sdk.AccAddress, 206 ) error { 207 if !types2.HigherThanVenus4(ctx.BlockHeight()) { 208 return im.v2Module.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer) 209 } 210 var ack channeltypes.Acknowledgement 211 if err := types.Marshal.GetProtocMarshal().UnmarshalJSON(acknowledgement, &ack); err != nil { 212 return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet acknowledgement: %v", err) 213 } 214 var data types.FungibleTokenPacketData 215 if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { 216 return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet data: %s", err.Error()) 217 } 218 219 if err := im.keeper.OnAcknowledgementPacket(ctx, packet, data, ack); err != nil { 220 return err 221 } 222 223 ctx.EventManager().EmitEvent( 224 sdk.NewEvent( 225 types.EventTypePacket, 226 sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), 227 sdk.NewAttribute(sdk.AttributeKeySender, data.Sender), 228 sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), 229 sdk.NewAttribute(types.AttributeKeyDenom, data.Denom), 230 sdk.NewAttribute(types.AttributeKeyAmount, data.Amount), 231 sdk.NewAttribute(types.AttributeKeyAck, ack.String()), 232 ), 233 ) 234 235 switch resp := ack.Response.(type) { 236 case *channeltypes.Acknowledgement_Result: 237 ctx.EventManager().EmitEvent( 238 sdk.NewEvent( 239 types.EventTypePacket, 240 sdk.NewAttribute(types.AttributeKeyAckSuccess, string(resp.Result)), 241 ), 242 ) 243 case *channeltypes.Acknowledgement_Error: 244 ctx.EventManager().EmitEvent( 245 sdk.NewEvent( 246 types.EventTypePacket, 247 sdk.NewAttribute(types.AttributeKeyAckError, resp.Error), 248 ), 249 ) 250 } 251 252 return nil 253 } 254 255 // OnTimeoutPacket implements the IBCModule interface 256 func (im IBCModule) OnTimeoutPacket( 257 ctx sdk.Context, 258 packet channeltypes.Packet, 259 relayer sdk.AccAddress, 260 ) error { 261 if !types2.HigherThanVenus4(ctx.BlockHeight()) { 262 return im.v2Module.OnTimeoutPacket(ctx, packet, relayer) 263 } 264 var data types.FungibleTokenPacketData 265 if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { 266 return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet data: %s", err.Error()) 267 } 268 // refund tokens 269 if err := im.keeper.OnTimeoutPacket(ctx, packet, data); err != nil { 270 return err 271 } 272 273 ctx.EventManager().EmitEvent( 274 sdk.NewEvent( 275 types.EventTypeTimeout, 276 sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), 277 sdk.NewAttribute(types.AttributeKeyRefundReceiver, data.Sender), 278 sdk.NewAttribute(types.AttributeKeyRefundDenom, data.Denom), 279 sdk.NewAttribute(types.AttributeKeyRefundAmount, data.Amount), 280 ), 281 ) 282 283 return nil 284 } 285 286 // IBCModule implements the ICS26 interface for transfer given the transfer keeper. 287 type IBCModule struct { 288 keeper keeper.Keeper 289 v2Module AppModule 290 } 291 292 func (im IBCModule) SendPacket(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI) error { 293 return errNotSupportICS20 294 } 295 296 func (im IBCModule) WriteAcknowledgement(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI, ack ibcexported.Acknowledgement) error { 297 return errNotSupportICS20 298 } 299 300 func (im IBCModule) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) { 301 panic(errNotSupportICS20) 302 } 303 304 func (im IBCModule) NegotiateAppVersion(ctx sdk.Context, order channeltypes.Order, connectionID string, portID string, counterparty channeltypes.Counterparty, proposedVersion string) (version string, err error) { 305 return "", errNotSupportICS20 306 }