Skip to content

Commit

Permalink
feat: implement allowed channels
Browse files Browse the repository at this point in the history
  • Loading branch information
johnletey committed Jun 23, 2024
1 parent 44c811a commit 23b7e83
Show file tree
Hide file tree
Showing 32 changed files with 1,708 additions and 150 deletions.
2 changes: 1 addition & 1 deletion e2e/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.21

require (
github.com/cosmos/cosmos-sdk v0.45.16
github.com/cosmos/ibc-go/v4 v4.6.0
github.com/gogo/protobuf v1.3.3
github.com/noble-assets/aura v1.0.0
github.com/strangelove-ventures/interchaintest/v4 v4.0.0-20231026153934-334934f17a68
Expand Down Expand Up @@ -42,7 +43,6 @@ require (
github.com/cosmos/go-bip39 v1.0.0 // indirect
github.com/cosmos/gorocksdb v1.2.0 // indirect
github.com/cosmos/iavl v0.19.5 // indirect
github.com/cosmos/ibc-go/v4 v4.5.1 // indirect
github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
Expand Down
4 changes: 2 additions & 2 deletions e2e/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,8 @@ github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4
github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw=
github.com/cosmos/iavl v0.19.5 h1:rGA3hOrgNxgRM5wYcSCxgQBap7fW82WZgY78V9po/iY=
github.com/cosmos/iavl v0.19.5/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw=
github.com/cosmos/ibc-go/v4 v4.5.1 h1:+P73X7aIikGAXBUJ9vP9rEbvdSuekt3KGXmAWCSYets=
github.com/cosmos/ibc-go/v4 v4.5.1/go.mod h1:2EOi40Bx/j6rJrtP1ui8k8yUAMpGybmL1EjakYqYv5U=
github.com/cosmos/ibc-go/v4 v4.6.0 h1:G7kiD4Zf8Wrxc8BXWIKuFnzI0W4wpvRPrl5HwdfTIsA=
github.com/cosmos/ibc-go/v4 v4.6.0/go.mod h1:ksiZHUypws0NVP50E3ea0ivVFO/bfS8q8yLg8yZ2ATQ=
github.com/cosmos/ledger-cosmos-go v0.12.4 h1:drvWt+GJP7Aiw550yeb3ON/zsrgW0jgh5saFCr7pDnw=
github.com/cosmos/ledger-cosmos-go v0.12.4/go.mod h1:fjfVWRf++Xkygt9wzCsjEBdjcf7wiiY35fv3ctT+k4M=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
Expand Down
66 changes: 63 additions & 3 deletions e2e/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
transfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types"
"github.com/strangelove-ventures/interchaintest/v4/ibc"
"github.com/strangelove-ventures/interchaintest/v4/testutil"
"github.com/stretchr/testify/require"
)

Expand All @@ -14,7 +16,7 @@ func TestMintBurn(t *testing.T) {
t.Parallel()

var wrapper Wrapper
ctx := Suite(t, &wrapper)
ctx := Suite(t, &wrapper, false)
validator := wrapper.chain.Validators[0]

// ASSERT: Minter has an allowance of 1 $USDY.
Expand Down Expand Up @@ -56,7 +58,7 @@ func TestMintTransferBurn(t *testing.T) {
t.Parallel()

var wrapper Wrapper
ctx := Suite(t, &wrapper)
ctx := Suite(t, &wrapper, false)
validator := wrapper.chain.Validators[0]

// ASSERT: Minter has an allowance of 1 $USDY.
Expand Down Expand Up @@ -115,7 +117,7 @@ func TestMintTransferBlockBurn(t *testing.T) {
t.Parallel()

var wrapper Wrapper
ctx := Suite(t, &wrapper)
ctx := Suite(t, &wrapper, false)
validator := wrapper.chain.Validators[0]

// ASSERT: Minter has an allowance of 1 $USDY.
Expand Down Expand Up @@ -191,3 +193,61 @@ func TestMintTransferBlockBurn(t *testing.T) {
// ASSERT: Burner has no allowance.
EnsureBurner(t, wrapper, ctx, wrapper.burner.FormattedAddress(), sdk.ZeroInt())
}

func TestIBCTransfer(t *testing.T) {
t.Parallel()

var wrapper Wrapper
ctx := Suite(t, &wrapper, true)
validator := wrapper.chain.Validators[0]

// ARRANGE: Mint 1 $USDY to Alice.
_, err := validator.ExecTx(
ctx, wrapper.minter.KeyName(),
"aura", "mint", wrapper.alice.FormattedAddress(), ONE.String(),
)
require.NoError(t, err)
// ARRANGE: Determine Bob's external address.
recipient := sdk.MustBech32ifyAddressBytes(wrapper.gaia.Config().Bech32Prefix, wrapper.bob.Address())

// ACT: Attempt to transfer out of Noble.
_, err = validator.SendIBCTransfer(ctx, "channel-0", wrapper.alice.KeyName(), ibc.WalletAmount{
Address: recipient,
Denom: "ausdy",
Amount: ONE.Int64(),
}, ibc.TransferOptions{})
// ASSERT: The action should've failed due to not allowed channel.
require.ErrorContains(t, err, "ausdy cannot be transferred over channel-0")

// ACT: Allow transfers over channel-0.
_, err = validator.ExecTx(
ctx, wrapper.owner.KeyName(),
"aura", "allow-channel", "channel-0",
)
require.NoError(t, err)
// ASSERT: channel-0 has been allowed.
EnsureChannel(t, wrapper, ctx, "channel-0")

// ACT: Transfer 1 $USDY out of Noble.
_, err = validator.SendIBCTransfer(ctx, "channel-0", wrapper.alice.KeyName(), ibc.WalletAmount{
Address: recipient,
Denom: "ausdy",
Amount: ONE.Int64(),
}, ibc.TransferOptions{})
require.NoError(t, err)

// ACT: Wait 10 blocks for packet to be relayed.
require.NoError(t, testutil.WaitForBlocks(ctx, 10, wrapper.gaia))

// ASSERT: Alice has no balance.
balance, err := wrapper.chain.GetBalance(ctx, wrapper.alice.FormattedAddress(), "ausdy")
require.NoError(t, err)
require.Zero(t, balance)
// ASSERT: Bob has 1 $USDY.
balance, err = wrapper.gaia.GetBalance(ctx, recipient, transfertypes.DenomTrace{
Path: "transfer/channel-0",
BaseDenom: "ausdy",
}.IBCDenom())
require.NoError(t, err)
require.Equal(t, ONE.Int64(), balance)
}
48 changes: 47 additions & 1 deletion e2e/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ import (
"github.com/strangelove-ventures/interchaintest/v4"
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
"github.com/strangelove-ventures/interchaintest/v4/ibc"
"github.com/strangelove-ventures/interchaintest/v4/relayer/rly"
"github.com/strangelove-ventures/interchaintest/v4/testreporter"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
)

type Wrapper struct {
chain *cosmos.CosmosChain
gaia *cosmos.CosmosChain

owner ibc.Wallet
minter ibc.Wallet
Expand All @@ -28,7 +30,7 @@ type Wrapper struct {
bob ibc.Wallet
}

func Suite(t *testing.T, wrapper *Wrapper) (ctx context.Context) {
func Suite(t *testing.T, wrapper *Wrapper, ibcEnabled bool) (ctx context.Context) {
ctx = context.Background()
logger := zaptest.NewLogger(t)
reporter := testreporter.NewNopReporter()
Expand Down Expand Up @@ -135,6 +137,14 @@ func Suite(t *testing.T, wrapper *Wrapper) (ctx context.Context) {
},
},
}
if ibcEnabled {
specs = append(specs, &interchaintest.ChainSpec{
Name: "ibc-go-simd",
Version: "v4.5.0",
NumValidators: &numValidators,
NumFullNodes: &numFullNodes,
})
}
factory := interchaintest.NewBuiltinChainFactory(logger, specs)

chains, err := factory.Chains(t.Name())
Expand All @@ -144,6 +154,26 @@ func Suite(t *testing.T, wrapper *Wrapper) (ctx context.Context) {
wrapper.chain = noble

interchain := interchaintest.NewInterchain().AddChain(noble)
var relayer *rly.CosmosRelayer
if ibcEnabled {
relayer = interchaintest.NewBuiltinRelayerFactory(
ibc.CosmosRly,
logger,
).Build(t, client, network).(*rly.CosmosRelayer)

gaia := chains[1].(*cosmos.CosmosChain)
wrapper.gaia = gaia

interchain = interchain.
AddChain(gaia).
AddRelayer(relayer, "relayer").
AddLink(interchaintest.InterchainLink{
Chain1: noble,
Chain2: gaia,
Relayer: relayer,
Path: "transfer",
})
}
require.NoError(t, interchain.Build(ctx, execReporter, interchaintest.InterchainBuildOptions{
TestName: t.Name(),
Client: client,
Expand All @@ -154,6 +184,10 @@ func Suite(t *testing.T, wrapper *Wrapper) (ctx context.Context) {
_ = interchain.Close()
})

if ibcEnabled {
require.NoError(t, relayer.StartRelayer(ctx, execReporter))
}

return
}

Expand Down Expand Up @@ -194,3 +228,15 @@ func EnsureMinter(t *testing.T, wrapper Wrapper, ctx context.Context, address st

require.Contains(t, res.Minters, types.Minter{Address: address, Allowance: allowance})
}

func EnsureChannel(t *testing.T, wrapper Wrapper, ctx context.Context, channel string) {
validator := wrapper.chain.Validators[0]

raw, _, err := validator.ExecQuery(ctx, "aura", "channels")
require.NoError(t, err)

var res types.QueryChannelsResponse
require.NoError(t, json.Unmarshal(raw, &res))

require.Contains(t, res.Channels, channel)
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.21
require (
cosmossdk.io/errors v1.0.0
github.com/cosmos/cosmos-sdk v0.45.16
github.com/cosmos/ibc-go/v4 v4.6.0
github.com/gogo/protobuf v1.3.3
github.com/golang/protobuf v1.5.3
github.com/golangci/golangci-lint v1.55.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4
github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw=
github.com/cosmos/iavl v0.19.5 h1:rGA3hOrgNxgRM5wYcSCxgQBap7fW82WZgY78V9po/iY=
github.com/cosmos/iavl v0.19.5/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw=
github.com/cosmos/ibc-go/v4 v4.6.0 h1:G7kiD4Zf8Wrxc8BXWIKuFnzI0W4wpvRPrl5HwdfTIsA=
github.com/cosmos/ibc-go/v4 v4.6.0/go.mod h1:ksiZHUypws0NVP50E3ea0ivVFO/bfS8q8yLg8yZ2ATQ=
github.com/cosmos/ledger-cosmos-go v0.12.4 h1:drvWt+GJP7Aiw550yeb3ON/zsrgW0jgh5saFCr7pDnw=
github.com/cosmos/ledger-cosmos-go v0.12.4/go.mod h1:fjfVWRf++Xkygt9wzCsjEBdjcf7wiiY35fv3ctT+k4M=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
Expand Down
6 changes: 6 additions & 0 deletions proto/aura/v1/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,9 @@ message PauserRemoved {
// address is the address of the pauser.
string address = 1;
}

// ChannelAllowed is emitted whenever a new channel is allowed.
message ChannelAllowed {
// channel is the id of the allowed channel.
string channel = 1;
}
3 changes: 3 additions & 0 deletions proto/aura/v1/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ message GenesisState {
repeated Minter minters = 6 [(gogoproto.nullable) = false];
// pausers is the list of addresses that can pause USDY.
repeated string pausers = 7;

// channels is the list of allowed IBC channels.
repeated string channels = 8;
}

//
Expand Down
10 changes: 10 additions & 0 deletions proto/aura/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ service Query {
rpc Pausers(aura.v1.QueryPausers) returns (aura.v1.QueryPausersResponse) {
option (google.api.http).get = "/aura/v1/pausers";
}

rpc Channels(aura.v1.QueryChannels) returns (aura.v1.QueryChannelsResponse) {
option (google.api.http).get = "/aura/v1/channels";
}
}

//
Expand Down Expand Up @@ -70,3 +74,9 @@ message QueryPausers {}
message QueryPausersResponse {
repeated string pausers = 1;
}

message QueryChannels {}

message QueryChannelsResponse {
repeated string channels = 1;
}
12 changes: 12 additions & 0 deletions proto/aura/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ service Msg {

rpc AddPauser(aura.v1.MsgAddPauser) returns (aura.v1.MsgAddPauserResponse);
rpc RemovePauser(aura.v1.MsgRemovePauser) returns (aura.v1.MsgRemovePauserResponse);

rpc AllowChannel(aura.v1.MsgAllowChannel) returns (aura.v1.MsgAllowChannelResponse);
}

//
Expand Down Expand Up @@ -190,3 +192,13 @@ message MsgRemovePauser {
}

message MsgRemovePauserResponse {}

message MsgAllowChannel {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string signer = 1;
string channel = 2;
}

message MsgAllowChannelResponse {}
75 changes: 75 additions & 0 deletions simapp/ante.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package simapp

import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/cosmos-sdk/x/auth/types"
ibcante "github.com/cosmos/ibc-go/v4/modules/core/ante"
ibckeeper "github.com/cosmos/ibc-go/v4/modules/core/keeper"
"github.com/noble-assets/aura/x/aura"
aurakeeper "github.com/noble-assets/aura/x/aura/keeper"
)

// HandlerOptions are the options required for constructing a default SDK AnteHandler.
type HandlerOptions struct {
AccountKeeper ante.AccountKeeper
AuraKeeper *aurakeeper.Keeper
BankKeeper types.BankKeeper
FeegrantKeeper ante.FeegrantKeeper
IBCKeeper *ibckeeper.Keeper
SignModeHandler authsigning.SignModeHandler
SigGasConsumer func(meter sdk.GasMeter, sig signing.SignatureV2, params types.Params) error
}

// NewAnteHandler returns an AnteHandler that checks and increments sequence
// numbers, checks signatures & account numbers, and deducts fees from the first
// signer.
func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
if options.AccountKeeper == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for ante builder")
}

if options.AuraKeeper == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "aura keeper is required for ante builder")
}

if options.BankKeeper == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for ante builder")
}

if options.IBCKeeper == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "ibc keeper is required for ante builder")
}

if options.SignModeHandler == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for ante builder")
}

sigGasConsumer := options.SigGasConsumer
if sigGasConsumer == nil {
sigGasConsumer = ante.DefaultSigVerificationGasConsumer
}

anteDecorators := []sdk.AnteDecorator{
ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
ante.NewRejectExtensionOptionsDecorator(),
ante.NewMempoolFeeDecorator(),
ante.NewValidateBasicDecorator(),
ante.NewTxTimeoutHeightDecorator(),
ante.NewValidateMemoDecorator(options.AccountKeeper),
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper),
ante.NewSetPubKeyDecorator(options.AccountKeeper), // SetPubKeyDecorator must be called before all signature verification decorators
ante.NewValidateSigCountDecorator(options.AccountKeeper),
ante.NewSigGasConsumeDecorator(options.AccountKeeper, sigGasConsumer),
ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
ibcante.NewAnteDecorator(options.IBCKeeper),
aura.NewAnteDecorator(options.AuraKeeper),
}

return sdk.ChainAnteDecorators(anteDecorators...), nil
}
Loading

0 comments on commit 23b7e83

Please sign in to comment.