729 lines
21 KiB
Go
729 lines
21 KiB
Go
package cli_test
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
abci "github.com/cometbft/cometbft/api/cometbft/abci/v1"
|
|
rpcclientmock "github.com/cometbft/cometbft/rpc/client/mock"
|
|
"github.com/cosmos/gogoproto/proto"
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
_ "cosmossdk.io/api/cosmos/feegrant/v1beta1"
|
|
v1 "cosmossdk.io/api/cosmos/gov/v1"
|
|
v1beta1 "cosmossdk.io/api/cosmos/gov/v1beta1"
|
|
"cosmossdk.io/core/address"
|
|
sdkmath "cosmossdk.io/math"
|
|
"cosmossdk.io/x/feegrant"
|
|
"cosmossdk.io/x/feegrant/client/cli"
|
|
"cosmossdk.io/x/feegrant/module"
|
|
"cosmossdk.io/x/gov"
|
|
govcli "cosmossdk.io/x/gov/client/cli"
|
|
|
|
"github.com/cosmos/cosmos-sdk/client"
|
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
|
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
|
|
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
|
|
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
|
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
|
"github.com/cosmos/cosmos-sdk/testutil"
|
|
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
testutilmod "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
|
)
|
|
|
|
const (
|
|
oneYear = 365 * 24 * 60 * 60
|
|
tenHours = 10 * 60 * 60
|
|
oneHour = 60 * 60
|
|
)
|
|
|
|
type CLITestSuite struct {
|
|
suite.Suite
|
|
|
|
addedGranter sdk.AccAddress
|
|
addedGrantee sdk.AccAddress
|
|
addedGrant feegrant.Grant
|
|
|
|
kr keyring.Keyring
|
|
baseCtx client.Context
|
|
encCfg testutilmod.TestEncodingConfig
|
|
clientCtx client.Context
|
|
|
|
accounts []sdk.AccAddress
|
|
}
|
|
|
|
func TestCLITestSuite(t *testing.T) {
|
|
suite.Run(t, new(CLITestSuite))
|
|
}
|
|
|
|
func (s *CLITestSuite) SetupSuite() {
|
|
s.T().Log("setting up integration test suite")
|
|
|
|
s.encCfg = testutilmod.MakeTestEncodingConfig(codectestutil.CodecOptions{}, module.AppModule{}, gov.AppModule{})
|
|
s.kr = keyring.NewInMemory(s.encCfg.Codec)
|
|
s.baseCtx = client.Context{}.
|
|
WithKeyring(s.kr).
|
|
WithTxConfig(s.encCfg.TxConfig).
|
|
WithCodec(s.encCfg.Codec).
|
|
WithClient(clitestutil.MockCometRPC{Client: rpcclientmock.Client{}}).
|
|
WithAccountRetriever(client.MockAccountRetriever{}).
|
|
WithOutput(io.Discard).
|
|
WithChainID("test-chain").
|
|
WithAddressCodec(addresscodec.NewBech32Codec("cosmos")).
|
|
WithValidatorAddressCodec(addresscodec.NewBech32Codec("cosmosvaloper")).
|
|
WithConsensusAddressCodec(addresscodec.NewBech32Codec("cosmosvalcons"))
|
|
|
|
ctxGen := func() client.Context {
|
|
bz, _ := s.encCfg.Codec.Marshal(&sdk.TxResponse{})
|
|
c := clitestutil.NewMockCometRPC(abci.QueryResponse{
|
|
Value: bz,
|
|
})
|
|
|
|
return s.baseCtx.WithClient(c)
|
|
}
|
|
s.clientCtx = ctxGen()
|
|
|
|
accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 2)
|
|
|
|
granter := accounts[0].Address
|
|
grantee := accounts[1].Address
|
|
s.createGrant(granter, grantee, s.baseCtx.AddressCodec)
|
|
|
|
granteeStr, err := s.baseCtx.AddressCodec.BytesToString(grantee)
|
|
s.Require().NoError(err)
|
|
granterStr, err := s.baseCtx.AddressCodec.BytesToString(granter)
|
|
s.Require().NoError(err)
|
|
|
|
grant, err := feegrant.NewGrant(granterStr, granteeStr, &feegrant.BasicAllowance{
|
|
SpendLimit: sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100))),
|
|
})
|
|
s.Require().NoError(err)
|
|
|
|
s.addedGrant = grant
|
|
s.addedGranter = granter
|
|
s.addedGrantee = grantee
|
|
for _, v := range accounts {
|
|
s.accounts = append(s.accounts, v.Address)
|
|
}
|
|
s.accounts[1] = accounts[1].Address
|
|
}
|
|
|
|
// createGrant creates a new basic allowance fee grant from granter to grantee.
|
|
func (s *CLITestSuite) createGrant(granter, grantee sdk.AccAddress, addressCodec address.Codec) {
|
|
commonFlags := []string{
|
|
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
|
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100))).String()),
|
|
}
|
|
|
|
fee := sdk.NewCoin("stake", sdkmath.NewInt(100))
|
|
|
|
granterAddr, err := addressCodec.BytesToString(granter)
|
|
s.Require().NoError(err)
|
|
granteeAddr, err := addressCodec.BytesToString(grantee)
|
|
s.Require().NoError(err)
|
|
|
|
args := append(
|
|
[]string{
|
|
granterAddr,
|
|
granteeAddr,
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, fee.String()),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
fmt.Sprintf("--%s=%s", cli.FlagExpiration, getFormattedExpiration(oneYear)),
|
|
},
|
|
commonFlags...,
|
|
)
|
|
|
|
cmd := cli.NewCmdFeeGrant()
|
|
out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, args)
|
|
s.Require().NoError(err)
|
|
|
|
var resp sdk.TxResponse
|
|
s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String())
|
|
s.Require().Equal(resp.Code, uint32(0))
|
|
}
|
|
|
|
func (s *CLITestSuite) TestNewCmdFeeGrant() {
|
|
granter := s.accounts[0]
|
|
clientCtx := s.clientCtx
|
|
granterAddr, err := s.baseCtx.AddressCodec.BytesToString(granter)
|
|
s.Require().NoError(err)
|
|
alreadyExistedGranteeAddr, err := s.baseCtx.AddressCodec.BytesToString(s.addedGrantee)
|
|
s.Require().NoError(err)
|
|
fromAddr, fromName, _, err := client.GetFromFields(s.baseCtx, s.kr, granterAddr)
|
|
s.Require().Equal(fromAddr, granter)
|
|
s.Require().NoError(err)
|
|
|
|
commonFlags := []string{
|
|
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
|
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
|
|
}
|
|
|
|
testCases := []struct {
|
|
name string
|
|
args []string
|
|
expectErr bool
|
|
expectedCode uint32
|
|
respType proto.Message
|
|
}{
|
|
{
|
|
"wrong granter address",
|
|
append(
|
|
[]string{
|
|
"wrong_granter",
|
|
"cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl",
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
true, 0, nil,
|
|
},
|
|
{
|
|
"wrong grantee address",
|
|
append(
|
|
[]string{
|
|
granterAddr,
|
|
"wrong_grantee",
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
true, 0, nil,
|
|
},
|
|
{
|
|
"wrong granter key name",
|
|
append(
|
|
[]string{
|
|
"invalid_granter",
|
|
"cosmos16dun6ehcc86e03wreqqww89ey569wuj4em572w",
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
true, 0, nil,
|
|
},
|
|
{
|
|
"valid basic fee grant",
|
|
append(
|
|
[]string{
|
|
granterAddr,
|
|
"cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl",
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
false, 0, &sdk.TxResponse{},
|
|
},
|
|
{
|
|
"valid basic fee grant with granter key name",
|
|
append(
|
|
[]string{
|
|
fromName,
|
|
"cosmos16dun6ehcc86e03wreqqww89ey569wuj4em572w",
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, fromName),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
false, 0, &sdk.TxResponse{},
|
|
},
|
|
{
|
|
"valid basic fee grant with amino",
|
|
append(
|
|
[]string{
|
|
granterAddr,
|
|
"cosmos1v57fx2l2rt6ehujuu99u2fw05779m5e2ux4z2h",
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
false, 0, &sdk.TxResponse{},
|
|
},
|
|
{
|
|
"valid basic fee grant without spend limit",
|
|
append(
|
|
[]string{
|
|
granterAddr,
|
|
"cosmos17h5lzptx3ghvsuhk7wx4c4hnl7rsswxjer97em",
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
false, 0, &sdk.TxResponse{},
|
|
},
|
|
{
|
|
"valid basic fee grant without expiration",
|
|
append(
|
|
[]string{
|
|
granterAddr,
|
|
"cosmos16dlc38dcqt0uralyd8hksxyrny6kaeqfjvjwp5",
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
false, 0, &sdk.TxResponse{},
|
|
},
|
|
{
|
|
"valid basic fee grant without spend-limit and expiration",
|
|
append(
|
|
[]string{
|
|
granterAddr,
|
|
"cosmos1ku40qup9vwag4wtf8cls9mkszxfthaklxkp3c8",
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
false, 0, &sdk.TxResponse{},
|
|
},
|
|
{
|
|
"try to add existed grant",
|
|
append(
|
|
[]string{
|
|
granterAddr,
|
|
alreadyExistedGranteeAddr,
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
false, 18, &sdk.TxResponse{},
|
|
},
|
|
{
|
|
"invalid number of args(periodic fee grant)",
|
|
append(
|
|
[]string{
|
|
granterAddr,
|
|
"cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl",
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
|
|
fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
fmt.Sprintf("--%s=%s", cli.FlagExpiration, getFormattedExpiration(tenHours)),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
true, 0, nil,
|
|
},
|
|
{
|
|
"period mentioned and period limit omitted, invalid periodic grant",
|
|
append(
|
|
[]string{
|
|
granterAddr,
|
|
"cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl",
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
|
|
fmt.Sprintf("--%s=%d", cli.FlagPeriod, tenHours),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
fmt.Sprintf("--%s=%s", cli.FlagExpiration, getFormattedExpiration(oneHour)),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
true, 0, nil,
|
|
},
|
|
{
|
|
"period cannot be greater than the actual expiration(periodic fee grant)",
|
|
append(
|
|
[]string{
|
|
granterAddr,
|
|
"cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl",
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
|
|
fmt.Sprintf("--%s=%d", cli.FlagPeriod, tenHours),
|
|
fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
fmt.Sprintf("--%s=%s", cli.FlagExpiration, getFormattedExpiration(oneHour)),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
true, 0, nil,
|
|
},
|
|
{
|
|
"valid periodic fee grant",
|
|
append(
|
|
[]string{
|
|
granterAddr,
|
|
"cosmos1w55kgcf3ltaqdy4ww49nge3klxmrdavrr6frmp",
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
|
|
fmt.Sprintf("--%s=%d", cli.FlagPeriod, oneHour),
|
|
fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
fmt.Sprintf("--%s=%s", cli.FlagExpiration, getFormattedExpiration(tenHours)),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
false, 0, &sdk.TxResponse{},
|
|
},
|
|
{
|
|
"valid periodic fee grant without spend-limit",
|
|
append(
|
|
[]string{
|
|
granterAddr,
|
|
"cosmos1vevyks8pthkscvgazc97qyfjt40m6g9xe85ry8",
|
|
fmt.Sprintf("--%s=%d", cli.FlagPeriod, oneHour),
|
|
fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
fmt.Sprintf("--%s=%s", cli.FlagExpiration, getFormattedExpiration(tenHours)),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
false, 0, &sdk.TxResponse{},
|
|
},
|
|
{
|
|
"valid periodic fee grant without expiration",
|
|
append(
|
|
[]string{
|
|
granterAddr,
|
|
"cosmos14cm33pvnrv2497tyt8sp9yavhmw83nwej3m0e8",
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
|
|
fmt.Sprintf("--%s=%d", cli.FlagPeriod, oneHour),
|
|
fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
false, 0, &sdk.TxResponse{},
|
|
},
|
|
{
|
|
"valid periodic fee grant without spend-limit and expiration",
|
|
append(
|
|
[]string{
|
|
granterAddr,
|
|
"cosmos12nyk4pcf4arshznkpz882e4l4ts0lt0ap8ce54",
|
|
fmt.Sprintf("--%s=%d", cli.FlagPeriod, oneHour),
|
|
fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
false, 0, &sdk.TxResponse{},
|
|
},
|
|
{
|
|
"invalid expiration",
|
|
append(
|
|
[]string{
|
|
granterAddr,
|
|
"cosmos1vevyks8pthkscvgazc97qyfjt40m6g9xe85ry8",
|
|
fmt.Sprintf("--%s=%d", cli.FlagPeriod, oneHour),
|
|
fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
fmt.Sprintf("--%s=%s", cli.FlagExpiration, "invalid"),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
true, 0, nil,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
tc := tc
|
|
|
|
s.Run(tc.name, func() {
|
|
cmd := cli.NewCmdFeeGrant()
|
|
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
|
|
|
|
if tc.expectErr {
|
|
s.Require().Error(err)
|
|
} else {
|
|
s.Require().NoError(err)
|
|
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (s *CLITestSuite) TestTxWithFeeGrant() {
|
|
clientCtx := s.clientCtx
|
|
granter := s.addedGranter
|
|
granterAddr, err := s.baseCtx.AddressCodec.BytesToString(granter)
|
|
s.Require().NoError(err)
|
|
|
|
// creating an account manually (This account won't be exist in state)
|
|
k, _, err := s.baseCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
|
|
s.Require().NoError(err)
|
|
pub, err := k.GetPubKey()
|
|
s.Require().NoError(err)
|
|
grantee := sdk.AccAddress(pub.Address())
|
|
granteeAddr, err := s.baseCtx.AddressCodec.BytesToString(grantee)
|
|
s.Require().NoError(err)
|
|
|
|
commonFlags := []string{
|
|
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
|
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
|
|
}
|
|
|
|
fee := sdk.NewCoin("stake", sdkmath.NewInt(100))
|
|
|
|
args := append(
|
|
[]string{
|
|
granterAddr,
|
|
granteeAddr,
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, fee.String()),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
fmt.Sprintf("--%s=%s", cli.FlagExpiration, getFormattedExpiration(oneYear)),
|
|
},
|
|
commonFlags...,
|
|
)
|
|
|
|
cmd := cli.NewCmdFeeGrant()
|
|
|
|
var res sdk.TxResponse
|
|
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
|
s.Require().NoError(err)
|
|
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &res), out.String())
|
|
|
|
testcases := []struct {
|
|
name string
|
|
from string
|
|
flags []string
|
|
expErrCode uint32
|
|
}{
|
|
{
|
|
name: "granted fee allowance for an account which is not in state and creating any tx with it by using --fee-granter shouldn't fail",
|
|
from: granteeAddr,
|
|
flags: []string{fmt.Sprintf("--%s=%s", flags.FlagFeeGranter, granterAddr)},
|
|
},
|
|
{
|
|
name: "--fee-payer should also sign the tx (direct)",
|
|
from: granteeAddr,
|
|
flags: []string{fmt.Sprintf("--%s=%s", flags.FlagFeePayer, granterAddr)},
|
|
expErrCode: 4,
|
|
},
|
|
{
|
|
name: "--fee-payer should also sign the tx (amino-json)",
|
|
from: granteeAddr,
|
|
flags: []string{
|
|
fmt.Sprintf("--%s=%s", flags.FlagFeePayer, granterAddr),
|
|
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON),
|
|
},
|
|
expErrCode: 4,
|
|
},
|
|
{
|
|
name: "use --fee-payer and --fee-granter together works",
|
|
from: granteeAddr,
|
|
flags: []string{
|
|
fmt.Sprintf("--%s=%s", flags.FlagFeePayer, granteeAddr),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFeeGranter, granterAddr),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range testcases {
|
|
s.Run(tc.name, func() {
|
|
err := s.msgSubmitLegacyProposal(s.baseCtx, tc.from,
|
|
"Text Proposal", "No desc", "text",
|
|
tc.flags...,
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
var resp sdk.TxResponse
|
|
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
func (s *CLITestSuite) msgSubmitLegacyProposal(clientCtx client.Context, from, title, description, proposalType string, extraArgs ...string) error {
|
|
commonArgs := []string{
|
|
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
|
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(10))).String()),
|
|
}
|
|
|
|
args := append([]string{
|
|
fmt.Sprintf("--%s=%s", govcli.FlagTitle, title),
|
|
fmt.Sprintf("--%s=%s", govcli.FlagDescription, description), //nolint:staticcheck // SA1019: govcli.FlagDescription is deprecated: use FlagDescription instead
|
|
fmt.Sprintf("--%s=%s", govcli.FlagProposalType, proposalType), //nolint:staticcheck // SA1019: govcli.FlagProposalType is deprecated: use FlagProposalType instead
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, from),
|
|
}, commonArgs...)
|
|
|
|
args = append(args, extraArgs...)
|
|
|
|
cmd := govcli.NewCmdSubmitLegacyProposal()
|
|
|
|
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
|
s.Require().NoError(err)
|
|
var resp sdk.TxResponse
|
|
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String())
|
|
|
|
return err
|
|
}
|
|
|
|
func (s *CLITestSuite) TestFilteredFeeAllowance() {
|
|
granter := s.addedGranter
|
|
granterAddr, err := s.baseCtx.AddressCodec.BytesToString(granter)
|
|
s.Require().NoError(err)
|
|
k, _, err := s.baseCtx.Keyring.NewMnemonic("grantee1", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
|
|
s.Require().NoError(err)
|
|
pub, err := k.GetPubKey()
|
|
s.Require().NoError(err)
|
|
grantee := sdk.AccAddress(pub.Address())
|
|
granteeAddr, err := s.baseCtx.AddressCodec.BytesToString(grantee)
|
|
s.Require().NoError(err)
|
|
clientCtx := s.clientCtx
|
|
|
|
commonFlags := []string{
|
|
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
|
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(100))).String()),
|
|
}
|
|
spendLimit := sdk.NewCoin("stake", sdkmath.NewInt(1000))
|
|
allowMsgs := strings.Join([]string{sdk.MsgTypeURL(&v1beta1.MsgSubmitProposal{}), sdk.MsgTypeURL(&v1.MsgVoteWeighted{})}, ",")
|
|
|
|
testCases := []struct {
|
|
name string
|
|
args []string
|
|
expectErrMsg string
|
|
}{
|
|
{
|
|
"invalid granter address",
|
|
append(
|
|
[]string{
|
|
"not an address",
|
|
"cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl",
|
|
fmt.Sprintf("--%s=%s", cli.FlagAllowedMsgs, allowMsgs),
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, spendLimit.String()),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
"key not found",
|
|
},
|
|
{
|
|
"invalid grantee address",
|
|
append(
|
|
[]string{
|
|
granterAddr,
|
|
"not an address",
|
|
fmt.Sprintf("--%s=%s", cli.FlagAllowedMsgs, allowMsgs),
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, spendLimit.String()),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
"decoding bech32 failed",
|
|
},
|
|
{
|
|
"valid filter fee grant",
|
|
append(
|
|
[]string{
|
|
granterAddr,
|
|
granteeAddr,
|
|
fmt.Sprintf("--%s=%s", cli.FlagAllowedMsgs, allowMsgs),
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, spendLimit.String()),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
|
},
|
|
commonFlags...,
|
|
),
|
|
"",
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
tc := tc
|
|
|
|
s.Run(tc.name, func() {
|
|
cmd := cli.NewCmdFeeGrant()
|
|
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
|
|
if tc.expectErrMsg != "" {
|
|
s.Require().Error(err)
|
|
s.Require().Contains(err.Error(), tc.expectErrMsg)
|
|
} else {
|
|
s.Require().NoError(err)
|
|
msg := &sdk.TxResponse{}
|
|
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String())
|
|
}
|
|
})
|
|
}
|
|
|
|
// exec filtered fee allowance
|
|
cases := []struct {
|
|
name string
|
|
malleate func() error
|
|
}{
|
|
{
|
|
"valid proposal tx",
|
|
func() error {
|
|
return s.msgSubmitLegacyProposal(s.baseCtx, granteeAddr,
|
|
"Text Proposal", "No desc", "Text",
|
|
fmt.Sprintf("--%s=%s", flags.FlagFeeGranter, granterAddr),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(100))).String()),
|
|
)
|
|
},
|
|
},
|
|
{
|
|
"valid weighted_vote tx",
|
|
func() error {
|
|
return s.msgVote(s.baseCtx, granteeAddr, "0", "yes",
|
|
fmt.Sprintf("--%s=%s", flags.FlagFeeGranter, granterAddr),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(100))).String()),
|
|
)
|
|
},
|
|
},
|
|
{
|
|
"should fail with unauthorized msgs",
|
|
func() error {
|
|
args := append(
|
|
[]string{
|
|
granteeAddr,
|
|
"cosmos14cm33pvnrv2497tyt8sp9yavhmw83nwej3m0e8",
|
|
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFeeGranter, granter),
|
|
},
|
|
commonFlags...,
|
|
)
|
|
|
|
cmd := cli.NewCmdFeeGrant()
|
|
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
|
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &sdk.TxResponse{}), out.String())
|
|
|
|
return err
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
tc := tc
|
|
|
|
s.Run(tc.name, func() {
|
|
err := tc.malleate()
|
|
s.Require().NoError(err)
|
|
})
|
|
}
|
|
}
|
|
|
|
// msgVote votes for a proposal
|
|
func (s *CLITestSuite) msgVote(clientCtx client.Context, from, id, vote string, extraArgs ...string) error {
|
|
commonArgs := []string{
|
|
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
|
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(10))).String()),
|
|
}
|
|
args := append([]string{
|
|
id,
|
|
vote,
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, from),
|
|
}, commonArgs...)
|
|
|
|
args = append(args, extraArgs...)
|
|
cmd := govcli.NewCmdWeightedVote()
|
|
|
|
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
|
|
|
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &sdk.TxResponse{}), out.String())
|
|
|
|
return err
|
|
}
|
|
|
|
func getFormattedExpiration(duration int64) string {
|
|
return time.Now().Add(time.Duration(duration) * time.Second).Format(time.RFC3339)
|
|
}
|