-
Notifications
You must be signed in to change notification settings - Fork 47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: auth, authz, bank e2e tests for fiattokenfactory #373
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,9 +8,11 @@ import ( | |
|
||
"cosmossdk.io/math" | ||
fiattokenfactorytypes "github.com/circlefin/noble-fiattokenfactory/x/fiattokenfactory/types" | ||
"github.com/cosmos/cosmos-sdk/crypto/keyring" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/noble-assets/noble/e2e" | ||
"github.com/strangelove-ventures/interchaintest/v8" | ||
"github.com/strangelove-ventures/interchaintest/v8/ibc" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
|
@@ -1521,3 +1523,326 @@ func TestFiatTFBurn(t *testing.T) { | |
require.NoError(t, err, "error getting balance") | ||
require.EqualValues(t, expectedAmount, bal.Int64()) | ||
} | ||
|
||
func TestFiatTFAuth(t *testing.T) { | ||
if testing.Short() { | ||
t.Skip() | ||
} | ||
t.Parallel() | ||
|
||
ctx := context.Background() | ||
|
||
nw := e2e.NobleSpinUp(t, ctx, true) | ||
noble := nw.Chain | ||
val := noble.Validators[0] | ||
|
||
// ACTION: Send non TF token but pay fee in TF token while the TF is paused | ||
// EXPECTED: Request fails; TF is paused | ||
|
||
originalAmount := math.OneInt() | ||
w := interchaintest.GetAndFundTestUsers(t, ctx, "default", originalAmount, noble, noble) | ||
alice := w[0] // 1ustake | ||
bob := w[1] // 1ustake | ||
|
||
mintAmount := int64(100) | ||
_, err := val.ExecTx(ctx, nw.FiatTfRoles.Minter.KeyName(), "fiat-tokenfactory", "mint", alice.FormattedAddress(), fmt.Sprintf("%duusdc", mintAmount)) | ||
require.NoError(t, err) | ||
|
||
e2e.PauseFiatTF(t, ctx, val, nw.FiatTfRoles.Pauser) | ||
|
||
sendAmount := 1 | ||
uusdcFee := int64(5) | ||
_, err = val.ExecTx(ctx, alice.KeyName(), "bank", "send", alice.KeyName(), bob.FormattedAddress(), fmt.Sprintf("%dustake", sendAmount), "--fees", fmt.Sprintf("%duusdc", uusdcFee)) | ||
require.ErrorContains(t, err, "the chain is paused") | ||
|
||
uStakebal, err := noble.GetBalance(ctx, alice.FormattedAddress(), "ustake") | ||
require.NoError(t, err) | ||
require.Equal(t, originalAmount, uStakebal) | ||
|
||
uusdcBal, err := noble.GetBalance(ctx, alice.FormattedAddress(), "uusdc") | ||
require.NoError(t, err) | ||
require.Equal(t, math.NewInt(mintAmount), uusdcBal) | ||
|
||
e2e.UnpauseFiatTF(t, ctx, val, nw.FiatTfRoles.Pauser) | ||
|
||
// ACTION: Send non TF token but pay fee in TF token while the sender is blacklisted | ||
// EXPECTED: Request fails | ||
|
||
e2e.BlacklistAccount(t, ctx, val, nw.FiatTfRoles.Blacklister, alice) | ||
|
||
_, err = val.ExecTx(ctx, alice.KeyName(), "bank", "send", alice.KeyName(), bob.FormattedAddress(), fmt.Sprintf("%dustake", sendAmount), "--fees", fmt.Sprintf("%duusdc", uusdcFee)) | ||
require.ErrorContains(t, err, fmt.Sprintf("an address (%s) is blacklisted and can not send tokens: unauthorized", alice.FormattedAddress())) | ||
|
||
bal, err := noble.GetBalance(ctx, alice.FormattedAddress(), "ustake") | ||
require.NoError(t, err) | ||
require.Equal(t, originalAmount, bal) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same question about checking the usdc balance There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added check in: 93925c1 |
||
uusdcBal, err = noble.GetBalance(ctx, alice.FormattedAddress(), "uusdc") | ||
require.NoError(t, err) | ||
require.Equal(t, math.NewInt(mintAmount), uusdcBal) | ||
|
||
e2e.UnblacklistAccount(t, ctx, val, nw.FiatTfRoles.Blacklister, alice) | ||
|
||
// ACTION: Successfully send non TF token but pay fee in TF token | ||
// EXPECTED: Success; Fee withdrawn from users balance | ||
|
||
_, err = val.ExecTx(ctx, alice.KeyName(), "bank", "send", alice.KeyName(), bob.FormattedAddress(), fmt.Sprintf("%dustake", sendAmount), "--fees", fmt.Sprintf("%duusdc", uusdcFee)) | ||
require.NoError(t, err) | ||
|
||
bobBalStake, err := noble.GetBalance(ctx, bob.FormattedAddress(), "ustake") | ||
require.NoError(t, err) | ||
require.Equal(t, originalAmount.Add(math.NewInt(int64(sendAmount))), bobBalStake) | ||
|
||
aliceBalUusdc, err := noble.GetBalance(ctx, alice.FormattedAddress(), "uusdc") | ||
require.NoError(t, err) | ||
require.EqualValues(t, mintAmount-uusdcFee, aliceBalUusdc.Int64()) | ||
} | ||
|
||
func TestFiatTFAuthzGrant(t *testing.T) { | ||
if testing.Short() { | ||
t.Skip() | ||
} | ||
t.Parallel() | ||
|
||
ctx := context.Background() | ||
|
||
nw := e2e.NobleSpinUp(t, ctx, true) | ||
noble := nw.Chain | ||
val := noble.Validators[0] | ||
|
||
// ACTION: Grant an authz SEND using a TF token while TF is paused | ||
// EXPECTED: Request fails | ||
|
||
w := interchaintest.GetAndFundTestUsers(t, ctx, "default", math.OneInt(), noble, noble) | ||
granter1 := w[0] | ||
grantee1 := w[1] | ||
|
||
e2e.PauseFiatTF(t, ctx, val, nw.FiatTfRoles.Pauser) | ||
|
||
_, err := val.AuthzGrant(ctx, granter1, grantee1.FormattedAddress(), "send", "--spend-limit=100uusdc") | ||
require.ErrorContains(t, err, "can not perform token authorizations: the chain is paused") | ||
|
||
e2e.UnpauseFiatTF(t, ctx, val, nw.FiatTfRoles.Pauser) | ||
|
||
// ACTION: Grant an authz SEND using a TF token to a grantee who is blacklisted | ||
// EXPECTED: Success; | ||
|
||
w = interchaintest.GetAndFundTestUsers(t, ctx, "default", math.OneInt(), noble, noble) | ||
granter2 := w[0] | ||
grantee2 := w[1] | ||
|
||
e2e.BlacklistAccount(t, ctx, val, nw.FiatTfRoles.Blacklister, grantee2) | ||
|
||
res, err := val.AuthzGrant(ctx, granter2, grantee2.FormattedAddress(), "send", "--spend-limit=100uusdc") | ||
require.NoError(t, err) | ||
require.Zero(t, res.Code) | ||
|
||
// ACTION: Grant an authz SEND using a TF token from a granter who is blacklisted | ||
// EXPECTED: Success; | ||
|
||
w = interchaintest.GetAndFundTestUsers(t, ctx, "default", math.OneInt(), noble, noble) | ||
granter3 := w[0] | ||
grantee3 := w[1] | ||
|
||
e2e.BlacklistAccount(t, ctx, val, nw.FiatTfRoles.Blacklister, granter3) | ||
|
||
res, err = val.AuthzGrant(ctx, granter3, grantee3.FormattedAddress(), "send", "--spend-limit=100uusdc") | ||
require.NoError(t, err) | ||
require.Zero(t, res.Code) | ||
} | ||
Comment on lines
+1639
to
+1652
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider Validating Authorization Grants After granting authorization (lines 1636-1652), it's good practice to verify that the authorization has been correctly recorded. Add assertions to confirm that the grantee has the expected authorization: res, err := val.AuthzListGrants(ctx, granter2, grantee2.FormattedAddress())
require.NoError(t, err)
require.Contains(t, res.Grants, /* expected grant details */) This ensures that the authorization grant is not only successful but also properly registered in the system. |
||
|
||
func TestFiatTFAuthzSend(t *testing.T) { | ||
if testing.Short() { | ||
t.Skip() | ||
} | ||
t.Parallel() | ||
|
||
ctx := context.Background() | ||
|
||
nw := e2e.NobleSpinUp(t, ctx, true) | ||
noble := nw.Chain | ||
val := noble.Validators[0] | ||
|
||
// setup | ||
w := interchaintest.GetAndFundTestUsers(t, ctx, "default", math.OneInt(), noble, noble, noble) | ||
granter := w[0] | ||
grantee := w[1] | ||
receiver := w[2] | ||
|
||
mintAmount := int64(100) | ||
_, err := val.ExecTx(ctx, nw.FiatTfRoles.Minter.KeyName(), "fiat-tokenfactory", "mint", granter.FormattedAddress(), fmt.Sprintf("%duusdc", mintAmount)) | ||
require.NoError(t, err, "error minting") | ||
|
||
res, err := val.AuthzGrant(ctx, granter, grantee.FormattedAddress(), "send", "--spend-limit=100uusdc") | ||
require.NoError(t, err) | ||
require.Zero(t, res.Code) | ||
|
||
sendAmount := int64(5) | ||
nestedCmd := []string{ | ||
noble.Config().Bin, | ||
"tx", "bank", "send", granter.FormattedAddress(), receiver.FormattedAddress(), fmt.Sprintf("%duusdc", sendAmount), | ||
"--from", granter.FormattedAddress(), "--generate-only", | ||
"--chain-id", noble.GetNode().Chain.Config().ChainID, | ||
"--node", noble.GetNode().Chain.GetRPCAddress(), | ||
"--home", noble.GetNode().HomeDir(), | ||
"--keyring-backend", keyring.BackendTest, | ||
"--output", "json", | ||
"--yes", | ||
} | ||
|
||
// ACTION: Execute an authz SEND using a TF token from a grantee who is blacklisted | ||
// EXPECTED: Request fails; Even though grantee is acting on behalf of the granter, | ||
// the granter still cannot execute `send` due to being blacklisted | ||
// Status: | ||
// Granter1 has authorized Grantee1 to send 100usdc from their wallet | ||
|
||
e2e.BlacklistAccount(t, ctx, val, nw.FiatTfRoles.Blacklister, grantee) | ||
|
||
_, err = val.AuthzExec(ctx, grantee, nestedCmd) | ||
require.ErrorContains(t, err, fmt.Sprintf("an address (%s) is blacklisted and can not authorize tokens: unauthorized", receiver.FormattedAddress())) | ||
Comment on lines
+1693
to
+1702
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct Error Message Check for Blacklisted Grantee In require.ErrorContains(t, err, fmt.Sprintf("an address (%s) is blacklisted and can not authorize tokens: unauthorized", receiver.FormattedAddress())) Since the grantee ( Apply this diff to correct the error message check: - require.ErrorContains(t, err, fmt.Sprintf("an address (%s) is blacklisted and can not authorize tokens: unauthorized", receiver.FormattedAddress()))
+ require.ErrorContains(t, err, fmt.Sprintf("an address (%s) is blacklisted and can not authorize tokens: unauthorized", grantee.FormattedAddress())) This ensures that the test accurately validates the error message corresponding to the blacklisted grantee. |
||
|
||
bal, err := noble.GetBalance(ctx, receiver.FormattedAddress(), "uusdc") | ||
require.NoError(t, err) | ||
require.True(t, bal.IsZero()) | ||
|
||
e2e.UnblacklistAccount(t, ctx, val, nw.FiatTfRoles.Blacklister, grantee) | ||
|
||
// ACTION: Execute an authz SEND using a TF token from a granter who is blacklisted | ||
// EXPECTED: Request fails; Granter is blacklisted | ||
// Status: | ||
// Granter1 has authorized Grantee1 to send 100usdc from their wallet | ||
|
||
e2e.BlacklistAccount(t, ctx, val, nw.FiatTfRoles.Blacklister, granter) | ||
|
||
_, err = val.AuthzExec(ctx, grantee, nestedCmd) | ||
require.ErrorContains(t, err, fmt.Sprintf("an address (%s) is blacklisted and can not send tokens: unauthorized", granter.FormattedAddress())) | ||
|
||
bal, err = noble.GetBalance(ctx, receiver.FormattedAddress(), "uusdc") | ||
require.NoError(t, err) | ||
require.True(t, bal.IsZero()) | ||
|
||
e2e.UnblacklistAccount(t, ctx, val, nw.FiatTfRoles.Blacklister, granter) | ||
|
||
// ACTION: Execute an authz SEND using a TF token to a receiver who is blacklisted | ||
// EXPECTED: Request fails; Granter is blacklisted | ||
// Status: | ||
// Granter1 has authorized Grantee1 to send 100usdc from their wallet | ||
|
||
e2e.BlacklistAccount(t, ctx, val, nw.FiatTfRoles.Blacklister, receiver) | ||
|
||
_, err = val.AuthzExec(ctx, grantee, nestedCmd) | ||
require.ErrorContains(t, err, fmt.Sprintf("an address (%s) is blacklisted and can not receive tokens: unauthorized", receiver.FormattedAddress())) | ||
|
||
bal, err = noble.GetBalance(ctx, receiver.FormattedAddress(), "uusdc") | ||
require.NoError(t, err) | ||
require.True(t, bal.IsZero()) | ||
|
||
e2e.UnblacklistAccount(t, ctx, val, nw.FiatTfRoles.Blacklister, receiver) | ||
|
||
// ACTION: Execute an authz SEND using a TF token while the TF is paused | ||
// EXPECTED: Request fails; chain is paused | ||
// Status: | ||
// Granter1 has authorized Grantee1 to send 100usdc from their wallet | ||
|
||
e2e.PauseFiatTF(t, ctx, val, nw.FiatTfRoles.Pauser) | ||
|
||
_, err = val.AuthzExec(ctx, grantee, nestedCmd) | ||
require.ErrorContains(t, err, "the chain is paused") | ||
|
||
bal, err = noble.GetBalance(ctx, receiver.FormattedAddress(), "uusdc") | ||
require.NoError(t, err) | ||
require.True(t, bal.IsZero()) | ||
|
||
e2e.UnpauseFiatTF(t, ctx, val, nw.FiatTfRoles.Pauser) | ||
|
||
Comment on lines
+1747
to
+1757
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure Proper Cleanup After Paused State In Add a call to // Ensure TF is unpaused after test
e2e.UnpauseFiatTF(t, ctx, val, nw.FiatTfRoles.Pauser) |
||
// ACTION: Happy path: Execute an authz SEND using a TF token | ||
// EXPECTED: Success; authz send is successful. | ||
// Status: | ||
// Granter1 has authorized Grantee1 to send 100usdc from their wallet | ||
|
||
_, err = val.AuthzExec(ctx, grantee, nestedCmd) | ||
require.NoError(t, err) | ||
|
||
bal, err = noble.GetBalance(ctx, receiver.FormattedAddress(), "uusdc") | ||
require.NoError(t, err) | ||
require.Equal(t, math.NewInt(sendAmount), bal) | ||
|
||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any value in adding a happy path test here (no accounts blacklisted, chain not paused)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think so, mainly to validate the test. Added: |
||
|
||
func TestFiatTFBankSend(t *testing.T) { | ||
if testing.Short() { | ||
t.Skip() | ||
} | ||
t.Parallel() | ||
|
||
ctx := context.Background() | ||
|
||
nw := e2e.NobleSpinUp(t, ctx, true) | ||
noble := nw.Chain | ||
val := noble.Validators[0] | ||
|
||
w := interchaintest.GetAndFundTestUsers(t, ctx, "default", math.OneInt(), noble, noble) | ||
alice := w[0] | ||
bob := w[1] | ||
|
||
mintAmount := int64(100) | ||
_, err := val.ExecTx(ctx, nw.FiatTfRoles.Minter.KeyName(), "fiat-tokenfactory", "mint", alice.FormattedAddress(), fmt.Sprintf("%duusdc", mintAmount)) | ||
require.NoError(t, err, "error minting") | ||
|
||
// ACTION: Send TF token while TF is paused | ||
// EXPECTED: Request fails; token not sent | ||
|
||
e2e.PauseFiatTF(t, ctx, val, nw.FiatTfRoles.Pauser) | ||
|
||
amountToSend := ibc.WalletAmount{ | ||
Address: bob.FormattedAddress(), | ||
Denom: "uusdc", | ||
Amount: math.OneInt(), | ||
} | ||
err = noble.SendFunds(ctx, alice.KeyName(), amountToSend) | ||
require.ErrorContains(t, err, "the chain is paused") | ||
|
||
bobBal, err := noble.GetBalance(ctx, bob.FormattedAddress(), "uusdc") | ||
require.NoError(t, err, "error getting balance") | ||
require.True(t, bobBal.IsZero()) | ||
|
||
e2e.UnpauseFiatTF(t, ctx, val, nw.FiatTfRoles.Pauser) | ||
|
||
// ACTION: Send TF token while FROM address is blacklisted | ||
// EXPECTED: Request fails; token not sent | ||
|
||
e2e.BlacklistAccount(t, ctx, val, nw.FiatTfRoles.Blacklister, alice) | ||
|
||
err = noble.SendFunds(ctx, alice.KeyName(), amountToSend) | ||
require.ErrorContains(t, err, fmt.Sprintf("an address (%s) is blacklisted and can not send tokens", alice.FormattedAddress())) | ||
|
||
bobBal, err = noble.GetBalance(ctx, bob.FormattedAddress(), "uusdc") | ||
require.NoError(t, err, "error getting balance") | ||
require.True(t, bobBal.IsZero()) | ||
|
||
e2e.UnblacklistAccount(t, ctx, val, nw.FiatTfRoles.Blacklister, alice) | ||
|
||
// ACTION: Send TF token while TO address is blacklisted | ||
// EXPECTED: Request fails; token not sent | ||
|
||
e2e.BlacklistAccount(t, ctx, val, nw.FiatTfRoles.Blacklister, bob) | ||
|
||
err = noble.SendFunds(ctx, alice.KeyName(), amountToSend) | ||
require.ErrorContains(t, err, fmt.Sprintf("an address (%s) is blacklisted and can not receive tokens", bob.FormattedAddress())) | ||
|
||
bobBal, err = noble.GetBalance(ctx, bob.FormattedAddress(), "uusdc") | ||
require.NoError(t, err, "error getting balance") | ||
require.True(t, bobBal.IsZero()) | ||
|
||
e2e.UnblacklistAccount(t, ctx, val, nw.FiatTfRoles.Blacklister, bob) | ||
|
||
// ACTION: Successfully send TF token | ||
// EXPECTED: Success | ||
|
||
err = noble.SendFunds(ctx, alice.KeyName(), amountToSend) | ||
require.NoError(t, err, "error sending funds") | ||
|
||
bobBal, err = noble.GetBalance(ctx, bob.FormattedAddress(), "uusdc") | ||
require.NoError(t, err, "error getting balance") | ||
require.Equal(t, amountToSend.Amount, bobBal) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the expected behaviour for the fees here? Are fees still charged (and so alice's USDC balance drops), or is the transaction dropped before fees are charged so the balance remains? Is this worth adding an assertion on?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call. The fee is not taken.
Added a check in: 93925c1