Skip to content

Commit

Permalink
chore: merge v9
Browse files Browse the repository at this point in the history
  • Loading branch information
johnletey committed Feb 7, 2025
2 parents 00f6725 + 7674b10 commit 893f00f
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 7 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ require (
cosmossdk.io/x/evidence v0.1.1
cosmossdk.io/x/feegrant v0.1.1
cosmossdk.io/x/upgrade v0.1.4
dollar.noble.xyz v1.0.0-alpha.3
dollar.noble.xyz v1.0.0-alpha.4
github.com/circlefin/noble-cctp v0.0.0-20241031192117-4285c94ec194
github.com/circlefin/noble-fiattokenfactory v0.0.0-20250123235012-5f9bd9dd2c5b
github.com/cometbft/cometbft v0.38.17
Expand All @@ -35,6 +35,7 @@ require (
github.com/spf13/cast v1.7.0
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.10.0
github.com/wormhole-foundation/wormhole/sdk v0.0.0-20241218143724-3797ed082150
jester.noble.xyz/api v0.1.0
mvdan.cc/gofumpt v0.7.0
Expand Down Expand Up @@ -297,7 +298,6 @@ require (
github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect
github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/testify v1.10.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
github.com/tdakkota/asciicheck v0.2.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,8 @@ cosmossdk.io/x/tx v0.13.8/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w=
cosmossdk.io/x/upgrade v0.1.4 h1:/BWJim24QHoXde8Bc64/2BSEB6W4eTydq0X/2f8+g38=
cosmossdk.io/x/upgrade v0.1.4/go.mod h1:9v0Aj+fs97O+Ztw+tG3/tp5JSlrmT7IcFhAebQHmOPo=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
dollar.noble.xyz v1.0.0-alpha.3 h1:lDCuwPKsMrdf6IXB6mBLzdnJekN3q1JmbSUg3jI2GwE=
dollar.noble.xyz v1.0.0-alpha.3/go.mod h1:xUIvQy23cN7ci4G/WkQ0Yu+tR6NxF/Khl0xuiyYcG4M=
dollar.noble.xyz v1.0.0-alpha.4 h1:DV5mRLjsQBikWKjXr027wHPNJM5r9TQ9TASgMhbVzbU=
dollar.noble.xyz v1.0.0-alpha.4/go.mod h1:75aH3kpPLDoQosHSvZYgm2DULvmDH5DAgcnt1FPkyk8=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/4meepo/tagalign v1.3.4 h1:P51VcvBnf04YkHzjfclN6BbsopfJR5rxs1n+5zHt+w8=
Expand Down
78 changes: 78 additions & 0 deletions ics4_wrapper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright 2025 NASD Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package noble

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types"
transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"
clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types"
porttypes "github.com/cosmos/ibc-go/v8/modules/core/05-port/types"
ibcexported "github.com/cosmos/ibc-go/v8/modules/core/exported"
)

var _ porttypes.ICS4Wrapper = &NobleICS4Wrapper{}

// NobleICS4Wrapper implements the ICS4Wrapper interface. It implements custom logic in SendPacket in order
// to check all outgoing IBC transfers so that $USDN cannot be sent to another chain.
type NobleICS4Wrapper struct {
ics4Wrapper porttypes.ICS4Wrapper
dollarKeeper ExpectedDollarKeeper
}

// ExpectedDollarKeeper defines the interface expected by NobleICS4Wrapper for the Noble Dollar module.
type ExpectedDollarKeeper interface {
GetDenom() string
}

// NewNobleICS4Wrapper returns a new instance of NobleICS4Wrapper.
func NewNobleICS4Wrapper(app porttypes.ICS4Wrapper, dollarKeeper ExpectedDollarKeeper) porttypes.ICS4Wrapper {
return NobleICS4Wrapper{
ics4Wrapper: app,
dollarKeeper: dollarKeeper,
}
}

// SendPacket attempts to unmarshal the provided packet data as the ICS-20
// FungibleTokenPacketData type. If the packet is a valid ICS-20 transfer, then
// a check is performed on the denom to ensure that $USDN cannot be transferred
// out of Noble via IBC.
func (w NobleICS4Wrapper) SendPacket(ctx sdk.Context, chanCap *capabilitytypes.Capability, sourcePort string, sourceChannel string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, data []byte) (sequence uint64, err error) {
var packetData transfertypes.FungibleTokenPacketData
if err := transfertypes.ModuleCdc.UnmarshalJSON(data, &packetData); err != nil {
return w.ics4Wrapper.SendPacket(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data)
}

denom := w.dollarKeeper.GetDenom()
if packetData.Denom == denom {
return 0, fmt.Errorf("ibc transfers of %s are currently disabled", denom)
}

return w.ics4Wrapper.SendPacket(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data)
}

// WriteAcknowledgement implements the ICS4Wrapper interface.
func (w NobleICS4Wrapper) WriteAcknowledgement(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI, ack ibcexported.Acknowledgement) error {
return w.ics4Wrapper.WriteAcknowledgement(ctx, chanCap, packet, ack)
}

// GetAppVersion implements the ICS4Wrapper interface.
func (w NobleICS4Wrapper) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) {
return w.ics4Wrapper.GetAppVersion(ctx, portID, channelID)
}
117 changes: 117 additions & 0 deletions ics4_wrapper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright 2025 NASD Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package noble

import (
"fmt"
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types"
transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"
clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types"
porttypes "github.com/cosmos/ibc-go/v8/modules/core/05-port/types"
"github.com/cosmos/ibc-go/v8/modules/core/exported"
"github.com/stretchr/testify/require"
)

var _ porttypes.ICS4Wrapper = (*MockICS4Wrapper)(nil)

type MockICS4Wrapper struct {
t *testing.T
}

func (m MockICS4Wrapper) SendPacket(
ctx sdk.Context,
chanCap *capabilitytypes.Capability,
sourcePort string,
sourceChannel string,
timeoutHeight clienttypes.Height,
timeoutTimestamp uint64,
data []byte,
) (sequence uint64, err error) {
return 0, nil
}

func (m MockICS4Wrapper) WriteAcknowledgement(
ctx sdk.Context,
chanCap *capabilitytypes.Capability,
packet exported.PacketI,
ack exported.Acknowledgement,
) error {
m.t.Fatal("WriteAcknowledgement should not have been called")
return nil
}

func (m MockICS4Wrapper) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) {
m.t.Fatal("GetAppVersion should not have been called")
return "", false
}

type MockDollarKeeper struct {
denom string
}

func (m MockDollarKeeper) GetDenom() string {
return m.denom
}

// TestSendPacket asserts that outgoing IBC transfers work as expected in cases
// where the denom is $USDN, as well as cases where the denom is not.
func TestSendPacket(t *testing.T) {
denom := "uusdn"

tc := []struct {
name string
data transfertypes.FungibleTokenPacketData
fail bool
}{
{
"Outgoing IBC transfer of USDN - should be blocked",
transfertypes.NewFungibleTokenPacketData(denom, "1000000", "test", "test", "test"),
true,
},
{
"Outgoing IBC transfer of USDC - should not be blocked",
transfertypes.NewFungibleTokenPacketData("uusdc", "1000000", "test", "test", "test"),
false,
},
}

for _, tt := range tc {
t.Run(tt.name, func(t *testing.T) {
wrapper := MockICS4Wrapper{t}
keeper := MockDollarKeeper{denom: denom}
nobleWrapper := NewNobleICS4Wrapper(wrapper, keeper)

data, err := transfertypes.ModuleCdc.MarshalJSON(&tt.data)
require.NoError(t, err)

ctx := sdk.Context{}
timeout := uint64(0)

_, err = nobleWrapper.SendPacket(ctx, nil, "transfer", "channel-0", clienttypes.Height{}, timeout, data)

if tt.fail {
require.Error(t, err)
require.ErrorContains(t, err, fmt.Sprintf("ibc transfers of %s are currently disabled", denom))
} else {
require.NoError(t, err)
}
})
}
}
7 changes: 4 additions & 3 deletions legacy.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package noble

import (
storetypes "cosmossdk.io/store/types"
dollar "dollar.noble.xyz"
"github.com/circlefin/noble-fiattokenfactory/x/blockibc"
pfm "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v8/packetforward"
pfmkeeper "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v8/packetforward/keeper"
Expand Down Expand Up @@ -96,12 +95,15 @@ func (app *App) RegisterLegacyModules() error {
)
app.ICAHostKeeper.WithQueryRouter(app.GRPCQueryRouter())

// Create custom ICS4Wrapper so that we can block outgoing $USDN IBC transfers.
ics4Wrapper := NewNobleICS4Wrapper(app.IBCKeeper.ChannelKeeper, app.DollarKeeper)

scopedTransferKeeper := app.CapabilityKeeper.ScopeToModule(transfertypes.ModuleName)
app.TransferKeeper = transferkeeper.NewKeeper(
app.appCodec,
app.GetKey(transfertypes.StoreKey),
app.GetSubspace(transfertypes.ModuleName),
app.IBCKeeper.ChannelKeeper,
ics4Wrapper,
app.IBCKeeper.ChannelKeeper,
app.IBCKeeper.PortKeeper,
app.AccountKeeper,
Expand All @@ -122,7 +124,6 @@ func (app *App) RegisterLegacyModules() error {

var transferStack porttypes.IBCModule
transferStack = transfer.NewIBCModule(app.TransferKeeper)
transferStack = dollar.NewIBCMiddleware(transferStack, app.IBCKeeper.ChannelKeeper, app.DollarKeeper)
transferStack = forwarding.NewMiddleware(transferStack, app.AccountKeeper, app.ForwardingKeeper)
transferStack = pfm.NewIBCMiddleware(
transferStack,
Expand Down

0 comments on commit 893f00f

Please sign in to comment.