github.com/Finschia/finschia-sdk@v0.49.1/x/auth/ante/feegrant_test.go (about) 1 package ante_test 2 3 import ( 4 "math/rand" 5 "testing" 6 "time" 7 8 "github.com/Finschia/ostracon/crypto" 9 10 "github.com/Finschia/finschia-sdk/client" 11 "github.com/Finschia/finschia-sdk/codec" 12 cryptotypes "github.com/Finschia/finschia-sdk/crypto/types" 13 "github.com/Finschia/finschia-sdk/simapp" 14 "github.com/Finschia/finschia-sdk/simapp/helpers" 15 "github.com/Finschia/finschia-sdk/testutil/testdata" 16 sdk "github.com/Finschia/finschia-sdk/types" 17 "github.com/Finschia/finschia-sdk/types/simulation" 18 "github.com/Finschia/finschia-sdk/types/tx/signing" 19 "github.com/Finschia/finschia-sdk/x/auth/ante" 20 authsign "github.com/Finschia/finschia-sdk/x/auth/signing" 21 "github.com/Finschia/finschia-sdk/x/auth/tx" 22 authtypes "github.com/Finschia/finschia-sdk/x/auth/types" 23 "github.com/Finschia/finschia-sdk/x/feegrant" 24 ) 25 26 func (suite *AnteTestSuite) TestDeductFeesNoDelegation() { 27 suite.SetupTest(false) 28 // setup 29 app, ctx := suite.app, suite.ctx 30 31 protoTxCfg := tx.NewTxConfig(codec.NewProtoCodec(app.InterfaceRegistry()), tx.DefaultSignModes) 32 33 // this just tests our handler 34 dfd := ante.NewDeductFeeDecorator(app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper) 35 feeAnteHandler := sdk.ChainAnteDecorators(dfd) 36 37 // this tests the whole stack 38 anteHandlerStack := suite.anteHandler 39 40 // keys and addresses 41 priv1, _, addr1 := testdata.KeyTestPubAddr() 42 priv2, _, addr2 := testdata.KeyTestPubAddr() 43 priv3, _, addr3 := testdata.KeyTestPubAddr() 44 priv4, _, addr4 := testdata.KeyTestPubAddr() 45 priv5, _, addr5 := testdata.KeyTestPubAddr() 46 47 // Set addr1 with insufficient funds 48 err := simapp.FundAccount(suite.app, suite.ctx, addr1, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(10))}) 49 suite.Require().NoError(err) 50 51 // Set addr2 with more funds 52 err = simapp.FundAccount(suite.app, suite.ctx, addr2, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(99999))}) 53 suite.Require().NoError(err) 54 55 // grant fee allowance from `addr2` to `addr3` (plenty to pay) 56 err = app.FeeGrantKeeper.GrantAllowance(ctx, addr2, addr3, &feegrant.BasicAllowance{ 57 SpendLimit: sdk.NewCoins(sdk.NewInt64Coin("atom", 500)), 58 }) 59 suite.Require().NoError(err) 60 61 // grant low fee allowance (20atom), to check the tx requesting more than allowed. 62 err = app.FeeGrantKeeper.GrantAllowance(ctx, addr2, addr4, &feegrant.BasicAllowance{ 63 SpendLimit: sdk.NewCoins(sdk.NewInt64Coin("atom", 20)), 64 }) 65 suite.Require().NoError(err) 66 67 cases := map[string]struct { 68 signerKey cryptotypes.PrivKey 69 signer sdk.AccAddress 70 feeAccount sdk.AccAddress 71 fee int64 72 valid bool 73 }{ 74 "paying with low funds": { 75 signerKey: priv1, 76 signer: addr1, 77 fee: 50, 78 valid: false, 79 }, 80 "paying with good funds": { 81 signerKey: priv2, 82 signer: addr2, 83 fee: 50, 84 valid: true, 85 }, 86 "paying with no account": { 87 signerKey: priv3, 88 signer: addr3, 89 fee: 1, 90 valid: false, 91 }, 92 "no fee with real account": { 93 signerKey: priv1, 94 signer: addr1, 95 fee: 0, 96 valid: true, 97 }, 98 "no fee with no account": { 99 signerKey: priv5, 100 signer: addr5, 101 fee: 0, 102 valid: false, 103 }, 104 "valid fee grant without account": { 105 signerKey: priv3, 106 signer: addr3, 107 feeAccount: addr2, 108 fee: 50, 109 valid: true, 110 }, 111 "no fee grant": { 112 signerKey: priv3, 113 signer: addr3, 114 feeAccount: addr1, 115 fee: 2, 116 valid: false, 117 }, 118 "allowance smaller than requested fee": { 119 signerKey: priv4, 120 signer: addr4, 121 feeAccount: addr2, 122 fee: 50, 123 valid: false, 124 }, 125 "granter cannot cover allowed fee grant": { 126 signerKey: priv4, 127 signer: addr4, 128 feeAccount: addr1, 129 fee: 50, 130 valid: false, 131 }, 132 } 133 134 for name, stc := range cases { 135 tc := stc // to make scopelint happy 136 suite.T().Run(name, func(t *testing.T) { 137 fee := sdk.NewCoins(sdk.NewInt64Coin("atom", tc.fee)) 138 msgs := []sdk.Msg{testdata.NewTestMsg(tc.signer)} 139 140 acc := app.AccountKeeper.GetAccount(ctx, tc.signer) 141 privs, accNums, seqs := []cryptotypes.PrivKey{tc.signerKey}, []uint64{0}, []uint64{0} 142 if acc != nil { 143 accNums, seqs = []uint64{acc.GetAccountNumber()}, []uint64{acc.GetSequence()} 144 } 145 146 tx, err := genTxWithFeeGranter(protoTxCfg, msgs, fee, helpers.DefaultGenTxGas, ctx.ChainID(), accNums, seqs, tc.feeAccount, privs...) 147 suite.Require().NoError(err) 148 _, err = feeAnteHandler(ctx, tx, false) // tests only feegrant ante 149 if tc.valid { 150 suite.Require().NoError(err) 151 } else { 152 suite.Require().Error(err) 153 } 154 155 _, err = anteHandlerStack(ctx, tx, false) // tests while stack 156 if tc.valid { 157 suite.Require().NoError(err) 158 } else { 159 suite.Require().Error(err) 160 } 161 }) 162 } 163 } 164 165 // don't consume any gas 166 func SigGasNoConsumer(meter sdk.GasMeter, sig []byte, pubkey crypto.PubKey, params authtypes.Params) error { 167 return nil 168 } 169 170 func genTxWithFeeGranter(gen client.TxConfig, msgs []sdk.Msg, feeAmt sdk.Coins, gas uint64, chainID string, accNums, 171 accSeqs []uint64, feeGranter sdk.AccAddress, priv ...cryptotypes.PrivKey, 172 ) (sdk.Tx, error) { 173 sigs := make([]signing.SignatureV2, len(priv)) 174 175 // create a random length memo 176 r := rand.New(rand.NewSource(time.Now().UnixNano())) 177 178 memo := simulation.RandStringOfLength(r, simulation.RandIntBetween(r, 0, 100)) 179 180 signMode := gen.SignModeHandler().DefaultMode() 181 182 // 1st round: set SignatureV2 with empty signatures, to set correct 183 // signer infos. 184 for i, p := range priv { 185 sigs[i] = signing.SignatureV2{ 186 PubKey: p.PubKey(), 187 Data: &signing.SingleSignatureData{ 188 SignMode: signMode, 189 }, 190 Sequence: accSeqs[i], 191 } 192 } 193 194 tx := gen.NewTxBuilder() 195 err := tx.SetMsgs(msgs...) 196 if err != nil { 197 return nil, err 198 } 199 err = tx.SetSignatures(sigs...) 200 if err != nil { 201 return nil, err 202 } 203 tx.SetMemo(memo) 204 tx.SetFeeAmount(feeAmt) 205 tx.SetGasLimit(gas) 206 tx.SetFeeGranter(feeGranter) 207 208 // 2nd round: once all signer infos are set, every signer can sign. 209 for i, p := range priv { 210 signerData := authsign.SignerData{ 211 ChainID: chainID, 212 AccountNumber: accNums[i], 213 Sequence: accSeqs[i], 214 } 215 signBytes, err := gen.SignModeHandler().GetSignBytes(signMode, signerData, tx.GetTx()) 216 if err != nil { 217 panic(err) 218 } 219 sig, err := p.Sign(signBytes) 220 if err != nil { 221 panic(err) 222 } 223 sigs[i].Data.(*signing.SingleSignatureData).Signature = sig 224 err = tx.SetSignatures(sigs...) 225 if err != nil { 226 panic(err) 227 } 228 } 229 230 return tx.GetTx(), nil 231 }