142 lines
4.3 KiB
Go
142 lines
4.3 KiB
Go
package fee_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/tendermint/tmlibs/log"
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk"
|
|
"github.com/cosmos/cosmos-sdk/modules/coin"
|
|
"github.com/cosmos/cosmos-sdk/modules/fee"
|
|
"github.com/cosmos/cosmos-sdk/stack"
|
|
"github.com/cosmos/cosmos-sdk/state"
|
|
)
|
|
|
|
func TestFeeChecks(t *testing.T) {
|
|
assert := assert.New(t)
|
|
require := require.New(t)
|
|
|
|
atom := func(i int64) coin.Coin { return coin.Coin{"atom", i} }
|
|
eth := func(i int64) coin.Coin { return coin.Coin{"eth", i} }
|
|
atoms := func(i int64) coin.Coins { return coin.Coins{{"atom", i}} }
|
|
wallet := func(i, j int64) coin.Coins { return coin.Coins{atom(i), eth(j)} }
|
|
|
|
// some coin amounts...
|
|
zero := coin.Coin{}
|
|
mixed := wallet(1200, 55)
|
|
pure := atoms(46657)
|
|
|
|
// these are some accounts
|
|
collector := sdk.Actor{App: fee.NameFee, Address: []byte("mine")}
|
|
key1 := coin.NewAccountWithKey(mixed)
|
|
key2 := coin.NewAccountWithKey(pure)
|
|
act1, act2 := key1.Actor(), key2.Actor()
|
|
|
|
// set up the apps....
|
|
disp := stack.NewDispatcher(
|
|
// OKHandler will just return success to a RawTx
|
|
stack.WrapHandler(stack.OKHandler{}),
|
|
// coin is needed to handle the IPC call from Fee middleware
|
|
coin.NewHandler(),
|
|
)
|
|
// app1 requires no fees
|
|
app1 := stack.New(fee.NewSimpleFeeMiddleware(atom(0), collector)).Use(disp)
|
|
// app2 requires 2 atom
|
|
app2 := stack.New(fee.NewSimpleFeeMiddleware(atom(2), collector)).Use(disp)
|
|
|
|
// set up the store and init the accounts
|
|
store := state.NewMemKVStore()
|
|
l := log.NewNopLogger()
|
|
_, err := app1.InitState(l, store, "coin", "account", key1.MakeOption())
|
|
require.Nil(err, "%+v", err)
|
|
_, err = app2.InitState(l, store, "coin", "account", key2.MakeOption())
|
|
require.Nil(err, "%+v", err)
|
|
|
|
// feeCost is what we expect if the fee is properly paid
|
|
feeCost := coin.CostSend * 2
|
|
cases := []struct {
|
|
valid bool
|
|
// this is the middleware stack to test
|
|
app sdk.Handler
|
|
// they sign the tx
|
|
signer sdk.Actor
|
|
// wrap with the given fee if hasFee is true
|
|
hasFee bool
|
|
payer sdk.Actor
|
|
fee coin.Coin
|
|
// expected balance after the tx
|
|
left coin.Coins
|
|
collected coin.Coins
|
|
// expected gas allocated
|
|
expectedCost uint64
|
|
}{
|
|
// make sure it works with no fee (control group)
|
|
{true, app1, act1, false, act1, zero, mixed, nil, 0},
|
|
{true, app1, act2, false, act2, zero, pure, nil, 0},
|
|
|
|
// no fee or too low is rejected
|
|
{false, app2, act1, false, act1, zero, mixed, nil, 0},
|
|
{false, app2, act2, false, act2, zero, pure, nil, 0},
|
|
{false, app2, act1, true, act1, zero, mixed, nil, 0},
|
|
{false, app2, act2, true, act2, atom(1), pure, nil, 0},
|
|
|
|
// proper fees are transfered in both cases
|
|
{true, app1, act1, true, act1, atom(1), wallet(1199, 55), atoms(1), feeCost},
|
|
{true, app2, act2, true, act2, atom(57), atoms(46600), atoms(58), feeCost},
|
|
|
|
// // fee must be the proper type...
|
|
{false, app1, act1, true, act1, eth(5), wallet(1199, 55), atoms(58), 0},
|
|
|
|
// signature must match
|
|
{false, app2, act1, true, act2, atom(5), atoms(46600), atoms(58), 0},
|
|
|
|
// send only works within limits
|
|
{true, app2, act1, true, act1, atom(1100), wallet(99, 55), atoms(1158), feeCost},
|
|
{false, app2, act1, true, act1, atom(500), wallet(99, 55), atoms(1158), 0},
|
|
}
|
|
|
|
for i, tc := range cases {
|
|
// build the tx
|
|
tx := stack.NewRawTx([]byte{7, 8, 9})
|
|
if tc.hasFee {
|
|
tx = fee.NewFee(tx, tc.fee, tc.payer)
|
|
}
|
|
|
|
// set up the permissions
|
|
ctx := stack.MockContext("x", 1).WithPermissions(tc.signer)
|
|
|
|
// call checktx...
|
|
cres, err := tc.app.CheckTx(ctx, store, tx)
|
|
if tc.valid {
|
|
assert.Nil(err, "%d: %+v", i, err)
|
|
assert.EqualValues(tc.fee.Amount, cres.GasPayment)
|
|
assert.EqualValues(tc.expectedCost, cres.GasAllocated)
|
|
} else {
|
|
assert.NotNil(err, "%d", i)
|
|
}
|
|
|
|
// call delivertx...
|
|
_, err = tc.app.DeliverTx(ctx, store, tx)
|
|
if tc.valid {
|
|
assert.Nil(err, "%d: %+v", i, err)
|
|
} else {
|
|
assert.NotNil(err, "%d", i)
|
|
}
|
|
|
|
// check the account balance afterwards....
|
|
cspace := stack.PrefixedStore(coin.NameCoin, store)
|
|
acct, err := coin.GetAccount(cspace, tc.payer)
|
|
require.Nil(err, "%d: %+v", i, err)
|
|
assert.Equal(tc.left, acct.Coins, "%d", i)
|
|
|
|
// check the collected balance afterwards....
|
|
acct, err = coin.GetAccount(cspace, collector)
|
|
require.Nil(err, "%d: %+v", i, err)
|
|
assert.Equal(tc.collected, acct.Coins, "%d", i)
|
|
}
|
|
|
|
}
|