diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index bf64f24f2..2321db835 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -14,6 +14,7 @@ import ( "github.com/tendermint/tendermint/libs/log" sdk "github.com/cosmos/cosmos-sdk/types" + authsim "github.com/cosmos/cosmos-sdk/x/auth/simulation" banksim "github.com/cosmos/cosmos-sdk/x/bank/simulation" distr "github.com/cosmos/cosmos-sdk/x/distribution" distributionsim "github.com/cosmos/cosmos-sdk/x/distribution/simulation" @@ -103,11 +104,12 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage { func testAndRunTxs(app *GaiaApp) []simulation.WeightedOperation { return []simulation.WeightedOperation{ + {5, authsim.SimulateDeductFee(app.accountMapper, app.feeCollectionKeeper)}, {100, banksim.SingleInputSendMsg(app.accountMapper, app.bankKeeper)}, {50, distributionsim.SimulateMsgSetWithdrawAddress(app.accountMapper, app.distrKeeper)}, - {50, distributionsim.SimulateMsgWithdrawDelegatorRewardsAll(app.accountMapper, app.distrKeeper)}, - {50, distributionsim.SimulateMsgWithdrawDelegatorReward(app.accountMapper, app.distrKeeper)}, - {50, distributionsim.SimulateMsgWithdrawValidatorRewardsAll(app.accountMapper, app.distrKeeper)}, + //{50, distributionsim.SimulateMsgWithdrawDelegatorRewardsAll(app.accountMapper, app.distrKeeper)}, + //{50, distributionsim.SimulateMsgWithdrawDelegatorReward(app.accountMapper, app.distrKeeper)}, + //{50, distributionsim.SimulateMsgWithdrawValidatorRewardsAll(app.accountMapper, app.distrKeeper)}, {5, govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, app.stakeKeeper)}, {100, govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper)}, {100, stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper)}, @@ -124,7 +126,7 @@ func invariants(app *GaiaApp) []simulation.Invariant { banksim.NonnegativeBalanceInvariant(app.accountMapper), distributionsim.AllInvariants(app.bankKeeper, app.distrKeeper, app.accountMapper), govsim.AllInvariants(), - stakesim.AllInvariants(app.bankKeeper, app.stakeKeeper, app.distrKeeper, app.accountMapper), + stakesim.AllInvariants(app.bankKeeper, app.stakeKeeper, app.feeCollectionKeeper, app.distrKeeper, app.accountMapper), slashingsim.AllInvariants(), } } diff --git a/x/auth/ante.go b/x/auth/ante.go index b6f880254..98536ab7a 100644 --- a/x/auth/ante.go +++ b/x/auth/ante.go @@ -93,7 +93,7 @@ func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler { if !res.IsOK() { return newCtx, res, true } - fck.addCollectedFees(newCtx, stdTx.Fee.Amount) + fck.AddCollectedFees(newCtx, stdTx.Fee.Amount) } for i := 0; i < len(stdSigs); i++ { diff --git a/x/auth/feekeeper.go b/x/auth/feekeeper.go index 45894be1b..83aa2b33b 100644 --- a/x/auth/feekeeper.go +++ b/x/auth/feekeeper.go @@ -46,7 +46,7 @@ func (fck FeeCollectionKeeper) setCollectedFees(ctx sdk.Context, coins sdk.Coins store.Set(collectedFeesKey, bz) } -func (fck FeeCollectionKeeper) addCollectedFees(ctx sdk.Context, coins sdk.Coins) sdk.Coins { +func (fck FeeCollectionKeeper) AddCollectedFees(ctx sdk.Context, coins sdk.Coins) sdk.Coins { newCoins := fck.GetCollectedFees(ctx).Plus(coins) fck.setCollectedFees(ctx, newCoins) diff --git a/x/auth/simulation/fake.go b/x/auth/simulation/fake.go new file mode 100644 index 000000000..99001617c --- /dev/null +++ b/x/auth/simulation/fake.go @@ -0,0 +1,55 @@ +package simulation + +import ( + "errors" + "fmt" + "math/big" + "math/rand" + + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/mock/simulation" +) + +// SimulateDeductFee +func SimulateDeductFee(m auth.AccountMapper, f auth.FeeCollectionKeeper) simulation.Operation { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simulation.Account, event func(string)) ( + action string, fOp []simulation.FutureOperation, err error) { + + account := simulation.RandomAcc(r, accs) + stored := m.GetAccount(ctx, account.Address) + initCoins := stored.GetCoins() + + if len(initCoins) == 0 { + event(fmt.Sprintf("auth/SimulateDeductFee/false")) + return action, nil, nil + } + + denomIndex := r.Intn(len(initCoins)) + amt, err := randPositiveInt(r, initCoins[denomIndex].Amount) + if err != nil { + event(fmt.Sprintf("auth/SimulateDeductFee/false")) + return action, nil, nil + } + + coins := sdk.Coins{sdk.NewCoin(initCoins[denomIndex].Denom, amt)} + stored.SetCoins(initCoins.Minus(coins)) + m.SetAccount(ctx, stored) + f.AddCollectedFees(ctx, coins) + + event(fmt.Sprintf("auth/SimulateDeductFee/true")) + + action = "TestDeductFee" + return action, nil, nil + } +} + +func randPositiveInt(r *rand.Rand, max sdk.Int) (sdk.Int, error) { + if !max.GT(sdk.OneInt()) { + return sdk.Int{}, errors.New("max too small") + } + max = max.Sub(sdk.OneInt()) + return sdk.NewIntFromBigInt(new(big.Int).Rand(r, max.BigInt())).Add(sdk.OneInt()), nil +} diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index e6dd1c969..748fdd00c 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -18,6 +18,7 @@ func (k Keeper) AllocateFees(ctx sdk.Context, percentVotes sdk.Dec, proposer sdk // get the fees which have been getting collected through all the // transactions in the block feesCollected := k.feeCollectionKeeper.GetCollectedFees(ctx) + fmt.Printf("fees collected: %v\n", feesCollected) feesCollectedDec := types.NewDecCoins(feesCollected) // allocated rewards to proposer diff --git a/x/mock/simulation/constants.go b/x/mock/simulation/constants.go index a96d4541f..f0f53222f 100644 --- a/x/mock/simulation/constants.go +++ b/x/mock/simulation/constants.go @@ -17,7 +17,7 @@ const ( evidenceFraction float64 = 0.5 // TODO Remove in favor of binary search for invariant violation - onOperation bool = false + onOperation bool = true ) var ( diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 7168bbdd6..1afbb341c 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -480,7 +480,14 @@ func (k Keeper) BeginUnbonding(ctx sdk.Context, return types.UnbondingDelegation{}, err } - balance := sdk.NewCoin(k.BondDenom(ctx), returnAmount.RoundInt()) + rounded := returnAmount.TruncateInt() + balance := sdk.NewCoin(k.BondDenom(ctx), rounded) + change := returnAmount.Sub(sdk.NewDecFromInt(rounded)) + + // for now, change is just burned + pool := k.GetPool(ctx) + pool.LooseTokens = pool.LooseTokens.Sub(change) + k.SetPool(ctx, pool) // no need to create the ubd object just complete now if completeNow { @@ -543,7 +550,15 @@ func (k Keeper) BeginRedelegation(ctx sdk.Context, delAddr sdk.AccAddress, return types.Redelegation{}, err } - returnCoin := sdk.Coin{k.BondDenom(ctx), returnAmount.RoundInt()} + rounded := returnAmount.TruncateInt() + returnCoin := sdk.NewCoin(k.BondDenom(ctx), rounded) + change := returnAmount.Sub(sdk.NewDecFromInt(rounded)) + + // for now, change is just burned + pool := k.GetPool(ctx) + pool.LooseTokens = pool.LooseTokens.Sub(change) + k.SetPool(ctx, pool) + dstValidator, found := k.GetValidator(ctx, valDstAddr) if !found { return types.Redelegation{}, types.ErrBadRedelegationDst(k.Codespace()) diff --git a/x/stake/simulation/invariants.go b/x/stake/simulation/invariants.go index 175338cdf..d906cdbcc 100644 --- a/x/stake/simulation/invariants.go +++ b/x/stake/simulation/invariants.go @@ -15,9 +15,9 @@ import ( // AllInvariants runs all invariants of the stake module. // Currently: total supply, positive power -func AllInvariants(ck bank.Keeper, k stake.Keeper, d distribution.Keeper, am auth.AccountMapper) simulation.Invariant { +func AllInvariants(ck bank.Keeper, k stake.Keeper, f auth.FeeCollectionKeeper, d distribution.Keeper, am auth.AccountMapper) simulation.Invariant { return func(app *baseapp.BaseApp) error { - err := SupplyInvariants(ck, k, d, am)(app) + err := SupplyInvariants(ck, k, f, d, am)(app) if err != nil { return err } @@ -32,7 +32,7 @@ func AllInvariants(ck bank.Keeper, k stake.Keeper, d distribution.Keeper, am aut // SupplyInvariants checks that the total supply reflects all held loose tokens, bonded tokens, and unbonding delegations // nolint: unparam -func SupplyInvariants(ck bank.Keeper, k stake.Keeper, d distribution.Keeper, am auth.AccountMapper) simulation.Invariant { +func SupplyInvariants(ck bank.Keeper, k stake.Keeper, f auth.FeeCollectionKeeper, d distribution.Keeper, am auth.AccountMapper) simulation.Invariant { return func(app *baseapp.BaseApp) error { ctx := app.NewContext(false, abci.Header{}) pool := k.GetPool(ctx) @@ -61,6 +61,9 @@ func SupplyInvariants(ck bank.Keeper, k stake.Keeper, d distribution.Keeper, am feePool := d.GetFeePool(ctx) + // add outstanding fees + loose = loose.Add(sdk.NewDecFromInt(f.GetCollectedFees(ctx).AmountOf("steak"))) + // add community pool loose = loose.Add(feePool.CommunityPool.AmountOf("steak"))