From e4b0534db0d4cea415f527204955fb952d3a29b7 Mon Sep 17 00:00:00 2001 From: John Letey Date: Mon, 29 Apr 2024 16:33:30 +0200 Subject: [PATCH] feat: finish send restrictions --- .github/README.md | 2 ++ x/aura/keeper/keeper.go | 29 ++++++++++++++-- x/aura/keeper/keeper_test.go | 64 ++++++++++++++++++++++++++++++++++++ x/aura/types/keys.go | 4 +++ 4 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 x/aura/keeper/keeper_test.go diff --git a/.github/README.md b/.github/README.md index 8e866fa..ecacb0e 100644 --- a/.github/README.md +++ b/.github/README.md @@ -2,4 +2,6 @@

Ondo's US Dollar Yield Token on Noble

+[![codecov](https://img.shields.io/codecov/c/gh/noble-assets/aura?token=U9QRRF82W7&labelColor=black)](https://codecov.io/gh/noble-assets/aura) + This repository includes the `x/aura` Cosmos SDK module implementation. diff --git a/x/aura/keeper/keeper.go b/x/aura/keeper/keeper.go index c87815d..86196c2 100644 --- a/x/aura/keeper/keeper.go +++ b/x/aura/keeper/keeper.go @@ -7,6 +7,7 @@ import ( "cosmossdk.io/collections" "cosmossdk.io/core/event" "cosmossdk.io/core/store" + "cosmossdk.io/errors" "cosmossdk.io/log" "github.com/cosmos/cosmos-sdk/codec" @@ -77,8 +78,10 @@ func NewKeeper( return keeper } -// SendRestrictionFn checks every USDY transfer on the Noble chain to and checks -// if transfers are currently paused. +// SendRestrictionFn executes the following checks against all USDY transfers: +// - Is the module currently paused? +// - If we're not minting, check the sender against the blocklist. +// - If we're not burning, check the recipient against the blocklist. func (k *Keeper) SendRestrictionFn(ctx context.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) (newToAddr sdk.AccAddress, err error) { if amount := amt.AmountOf(k.Denom); !amount.IsZero() { paused, _ := k.Paused.Get(ctx) @@ -86,7 +89,27 @@ func (k *Keeper) SendRestrictionFn(ctx context.Context, fromAddr, toAddr sdk.Acc return toAddr, fmt.Errorf("%s transfers are paused", k.Denom) } - // TODO(@john): Discuss with Ondo the checks needed here. + if !fromAddr.Equals(types.ModuleAddress) { + has, err := k.BlockedAddresses.Has(ctx, fromAddr) + if err != nil { + return toAddr, errors.Wrap(err, "unable to retrieve blocked address") + } + if has { + address, _ := k.accountKeeper.AddressCodec().BytesToString(fromAddr) + return toAddr, fmt.Errorf("%s is blocked from sending %s", address, k.Denom) + } + } + + if !toAddr.Equals(types.ModuleAddress) { + has, err := k.BlockedAddresses.Has(ctx, toAddr) + if err != nil { + return toAddr, errors.Wrap(err, "unable to retrieve blocked address") + } + if has { + address, _ := k.accountKeeper.AddressCodec().BytesToString(toAddr) + return toAddr, fmt.Errorf("%s is blocked from receiving %s", address, k.Denom) + } + } } return toAddr, nil diff --git a/x/aura/keeper/keeper_test.go b/x/aura/keeper/keeper_test.go new file mode 100644 index 0000000..5371b81 --- /dev/null +++ b/x/aura/keeper/keeper_test.go @@ -0,0 +1,64 @@ +package keeper_test + +import ( + "testing" + + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/noble-assets/aura/utils" + "github.com/noble-assets/aura/utils/mocks" + "github.com/stretchr/testify/require" +) + +func TestSendRestriction(t *testing.T) { + keeper, ctx := mocks.AuraKeeper(t) + from, to := utils.TestAccount(), utils.TestAccount() + + // ACT: Attempt to send 1 USDC. + _, err := keeper.SendRestrictionFn(ctx, from.Bytes, to.Bytes, sdk.NewCoins(sdk.NewCoin( + "uusdc", math.NewInt(1_000_000), + ))) + // ASSERT: Action should succeed as it's not USDY. + require.NoError(t, err) + + // ACT: Attempt to send 1 USDY. + _, err = keeper.SendRestrictionFn(ctx, from.Bytes, to.Bytes, sdk.NewCoins(sdk.NewCoin( + keeper.Denom, ONE, + ))) + // ASSERT: Action should succeed. + require.NoError(t, err) + + // ARRANGE: Set paused state to true. + require.NoError(t, keeper.Paused.Set(ctx, true)) + + // ACT: Attempt to send 1 USDY when paused. + _, err = keeper.SendRestrictionFn(ctx, from.Bytes, to.Bytes, sdk.NewCoins(sdk.NewCoin( + keeper.Denom, ONE, + ))) + // ASSERT: Action should succeed. + require.ErrorContains(t, err, "ausdy transfers are paused") + + // ARRANGE: Set paused state to false. + require.NoError(t, keeper.Paused.Set(ctx, false)) + // ARRANGE: Block from address. + require.NoError(t, keeper.BlockedAddresses.Set(ctx, from.Bytes, true)) + + // ACT: Attempt to send 1 USDY from blocklisted address. + _, err = keeper.SendRestrictionFn(ctx, from.Bytes, to.Bytes, sdk.NewCoins(sdk.NewCoin( + keeper.Denom, ONE, + ))) + // ASSERT: Action should've failed due to blocked sender. + require.ErrorContains(t, err, "blocked from sending") + + // ARRANGE: Unblock from address. + require.NoError(t, keeper.BlockedAddresses.Remove(ctx, from.Bytes)) + // ARRANGE: Block to address. + require.NoError(t, keeper.BlockedAddresses.Set(ctx, to.Bytes, true)) + + // ACT: Attempt to send 1 USDY to blocklisted address. + _, err = keeper.SendRestrictionFn(ctx, from.Bytes, to.Bytes, sdk.NewCoins(sdk.NewCoin( + keeper.Denom, ONE, + ))) + // ASSERT: Action should've failed due to blocked recipient. + require.ErrorContains(t, err, "blocked from receiving") +} diff --git a/x/aura/types/keys.go b/x/aura/types/keys.go index b546c89..81398dd 100644 --- a/x/aura/types/keys.go +++ b/x/aura/types/keys.go @@ -1,7 +1,11 @@ package types +import authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + const ModuleName = "aura" +var ModuleAddress = authtypes.NewModuleAddress(ModuleName) + var ( PausedKey = []byte("paused") BurnerPrefix = []byte("burner/")