From f8ddfca7716a053dc17fab040f4cbca1509f5741 Mon Sep 17 00:00:00 2001 From: Spoorthi Satheesha <9302666+spoo-bar@users.noreply.github.com> Date: Thu, 13 Apr 2023 17:39:52 +0100 Subject: [PATCH 01/15] create block rewards for flat fees --- x/rewards/keeper/distribution.go | 14 ++++++++++++++ x/rewards/keeper/flat_fee.go | 10 ++++++++++ 2 files changed, 24 insertions(+) diff --git a/x/rewards/keeper/distribution.go b/x/rewards/keeper/distribution.go index bde2eb9c..8aa94840 100644 --- a/x/rewards/keeper/distribution.go +++ b/x/rewards/keeper/distribution.go @@ -37,11 +37,25 @@ type ( func (k Keeper) AllocateBlockRewards(ctx sdk.Context, height int64) { blockDistrState := k.estimateBlockGasUsage(ctx, height) blockDistrState = k.estimateBlockRewards(ctx, blockDistrState) + k.createFlatFeeRewards(ctx, height) k.createRewardsRecords(ctx, blockDistrState) k.cleanupRewardsPool(ctx, blockDistrState) k.cleanupTracking(ctx, height) } +func (k Keeper) createFlatFeeRewards(ctx sdk.Context, height int64) { + blockGasTrackingInfo := k.trackingKeeper.GetBlockTrackingInfo(ctx, height) + for _, txs := range blockGasTrackingInfo.GetTxs() { + for _, contractOp := range txs.GetContractOperations() { + contractAddr := sdk.MustAccAddressFromBech32(contractOp.ContractAddress) + fee, found := k.GetFlatFee(ctx, contractAddr) + if found { + k.CreateFlatFeeRewardsRecords(ctx, contractAddr, fee) + } + } + } +} + // estimateBlockGasUsage creates a new distribution state for the given block height. // Func iterates over all tracked transactions and estimates gas usage for each contract (on block and tx levels) merging operations. func (k Keeper) estimateBlockGasUsage(ctx sdk.Context, height int64) *blockRewardsDistributionState { diff --git a/x/rewards/keeper/flat_fee.go b/x/rewards/keeper/flat_fee.go index 4457ea67..d557e9de 100644 --- a/x/rewards/keeper/flat_fee.go +++ b/x/rewards/keeper/flat_fee.go @@ -41,3 +41,13 @@ func (k Keeper) GetFlatFee(ctx sdk.Context, contractAddr sdk.AccAddress) (sdk.Co return fee, true } + +func (k Keeper) CreateFlatFeeRewardsRecords(ctx sdk.Context, contractAddress sdk.AccAddress, flatfee sdk.Coin) { + rewardsRecordState := k.state.RewardsRecord(ctx) + calculationHeight, calculationTime := ctx.BlockHeight(), ctx.BlockTime() + + metadata := k.GetContractMetadata(ctx, contractAddress) + rewardsAddr := sdk.MustAccAddressFromBech32(metadata.RewardsAddress) + + rewardsRecordState.CreateRewardsRecord(rewardsAddr, sdk.NewCoins(flatfee), calculationHeight, calculationTime) +} From a3f90c32d10468a8c74a68034f2ebada1d06b023 Mon Sep 17 00:00:00 2001 From: Spoorthi Satheesha <9302666+spoo-bar@users.noreply.github.com> Date: Fri, 14 Apr 2023 10:09:34 +0100 Subject: [PATCH 02/15] moving flatfee feward record to ante --- x/rewards/ante/min_cons_fee.go | 2 ++ x/rewards/keeper/distribution.go | 14 -------------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/x/rewards/ante/min_cons_fee.go b/x/rewards/ante/min_cons_fee.go index 53d3b427..d7ed85c0 100644 --- a/x/rewards/ante/min_cons_fee.go +++ b/x/rewards/ante/min_cons_fee.go @@ -14,6 +14,7 @@ import ( type RewardsFeeReaderExpected interface { GetMinConsensusFee(ctx sdk.Context) (sdk.DecCoin, bool) GetFlatFee(ctx sdk.Context, contractAddr sdk.AccAddress) (sdk.Coin, bool) + CreateFlatFeeRewardsRecords(ctx sdk.Context, contractAddress sdk.AccAddress, flatfee sdk.Coin) } // MinFeeDecorator rejects transaction if its fees are less than minimum fees defined by the x/rewards module. @@ -87,6 +88,7 @@ func (mfd MinFeeDecorator) getContractFlatFees(ctx sdk.Context, m sdk.Msg) (sdk. } fee, found := mfd.rewardsKeeper.GetFlatFee(ctx, ca) if found { + mfd.rewardsKeeper.CreateFlatFeeRewardsRecords(ctx, ca, fee) return sdk.NewCoins(fee), nil } } diff --git a/x/rewards/keeper/distribution.go b/x/rewards/keeper/distribution.go index 8aa94840..bde2eb9c 100644 --- a/x/rewards/keeper/distribution.go +++ b/x/rewards/keeper/distribution.go @@ -37,25 +37,11 @@ type ( func (k Keeper) AllocateBlockRewards(ctx sdk.Context, height int64) { blockDistrState := k.estimateBlockGasUsage(ctx, height) blockDistrState = k.estimateBlockRewards(ctx, blockDistrState) - k.createFlatFeeRewards(ctx, height) k.createRewardsRecords(ctx, blockDistrState) k.cleanupRewardsPool(ctx, blockDistrState) k.cleanupTracking(ctx, height) } -func (k Keeper) createFlatFeeRewards(ctx sdk.Context, height int64) { - blockGasTrackingInfo := k.trackingKeeper.GetBlockTrackingInfo(ctx, height) - for _, txs := range blockGasTrackingInfo.GetTxs() { - for _, contractOp := range txs.GetContractOperations() { - contractAddr := sdk.MustAccAddressFromBech32(contractOp.ContractAddress) - fee, found := k.GetFlatFee(ctx, contractAddr) - if found { - k.CreateFlatFeeRewardsRecords(ctx, contractAddr, fee) - } - } - } -} - // estimateBlockGasUsage creates a new distribution state for the given block height. // Func iterates over all tracked transactions and estimates gas usage for each contract (on block and tx levels) merging operations. func (k Keeper) estimateBlockGasUsage(ctx sdk.Context, height int64) *blockRewardsDistributionState { From 4797308fa4b85ea046d0e86a3335451f9bb1f6b4 Mon Sep 17 00:00:00 2001 From: Spoorthi Satheesha <9302666+spoo-bar@users.noreply.github.com> Date: Fri, 14 Apr 2023 11:42:08 +0100 Subject: [PATCH 03/15] fixing ante test --- e2e/rewards_test.go | 2 +- x/rewards/ante/min_cons_fee_test.go | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/e2e/rewards_test.go b/e2e/rewards_test.go index 3420b09a..e4efeecf 100644 --- a/e2e/rewards_test.go +++ b/e2e/rewards_test.go @@ -414,7 +414,7 @@ func (s *E2ETestSuite) TestTXFailsAfterAnteHandler() { RewardsAddress: contractAddr.String(), }) - err := chain.GetApp().RewardsKeeper.SetFlatFee(chain.GetContext(), senderAcc.Address, rewardsTypes.FlatFee{ + err := rewardsKeeper.SetFlatFee(chain.GetContext(), senderAcc.Address, rewardsTypes.FlatFee{ ContractAddress: contractAddr.String(), FlatFee: sdk.NewInt64Coin("stake", 1000), }) diff --git a/x/rewards/ante/min_cons_fee_test.go b/x/rewards/ante/min_cons_fee_test.go index e79a8a95..8410458e 100644 --- a/x/rewards/ante/min_cons_fee_test.go +++ b/x/rewards/ante/min_cons_fee_test.go @@ -117,6 +117,7 @@ func TestRewardsContractFlatFeeAnteHandler(t *testing.T) { contractViewer.AddContractAdmin(contractFlatFeeDiffDenomSet.String(), contractAdminAcc.Address.String()) var metaCurrentDiff rewardsTypes.ContractMetadata metaCurrentDiff.ContractAddress = contractFlatFeeDiffDenomSet.String() + metaCurrentDiff.RewardsAddress = contractAdminAcc.Address.String() metaCurrentDiff.OwnerAddress = contractAdminAcc.Address.String() err = chain.GetApp().RewardsKeeper.SetContractMetadata(ctx, contractAdminAcc.Address, contractFlatFeeDiffDenomSet, metaCurrentDiff) require.NoError(t, err) @@ -132,6 +133,7 @@ func TestRewardsContractFlatFeeAnteHandler(t *testing.T) { contractViewer.AddContractAdmin(contractFlatFeeSameDenomSet.String(), contractAdminAcc.Address.String()) var metaCurrentSame rewardsTypes.ContractMetadata metaCurrentSame.ContractAddress = contractFlatFeeSameDenomSet.String() + metaCurrentSame.RewardsAddress = contractAdminAcc.Address.String() metaCurrentSame.OwnerAddress = contractAdminAcc.Address.String() err = chain.GetApp().RewardsKeeper.SetContractMetadata(ctx, contractAdminAcc.Address, contractFlatFeeSameDenomSet, metaCurrentSame) require.NoError(t, err) From 475184bc8885b0800d9aa2aff2a148f22e9d090f Mon Sep 17 00:00:00 2001 From: Spoorthi Satheesha <9302666+spoo-bar@users.noreply.github.com> Date: Fri, 14 Apr 2023 16:41:13 +0100 Subject: [PATCH 04/15] refactor msg type check --- app/ante.go | 2 +- x/rewards/ante/ante_utils.go | 60 ++++++++++++++++++++++++++++ x/rewards/ante/fee_deduction.go | 26 ++++++++---- x/rewards/ante/fee_deduction_test.go | 2 +- x/rewards/ante/min_cons_fee.go | 52 +++--------------------- 5 files changed, 85 insertions(+), 57 deletions(-) create mode 100644 x/rewards/ante/ante_utils.go diff --git a/app/ante.go b/app/ante.go index 473b0c16..7da37831 100644 --- a/app/ante.go +++ b/app/ante.go @@ -76,7 +76,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) { // Custom Archway interceptor to track new transactions trackingAnte.NewTxGasTrackingDecorator(options.TrackingKeeper), // Custom Archway fee deduction, which splits fees between x/rewards and x/auth fee collector - rewardsAnte.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.RewardsKeeper), + rewardsAnte.NewDeductFeeDecorator(options.Codec, options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.RewardsKeeper), // SetPubKeyDecorator must be called before all signature verification decorators ante.NewSetPubKeyDecorator(options.AccountKeeper), ante.NewValidateSigCountDecorator(options.AccountKeeper), diff --git a/x/rewards/ante/ante_utils.go b/x/rewards/ante/ante_utils.go new file mode 100644 index 00000000..02d29c1e --- /dev/null +++ b/x/rewards/ante/ante_utils.go @@ -0,0 +1,60 @@ +package ante + +import ( + wasmTypes "github.com/CosmWasm/wasmd/x/wasm/types" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkErrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/authz" +) + +// RewardsKeeperExpected defines the expected interface for the x/rewards keeper. +type RewardsKeeperExpected interface { + // Used in MinFeeDecorator + GetMinConsensusFee(ctx sdk.Context) (sdk.DecCoin, bool) + GetFlatFee(ctx sdk.Context, contractAddr sdk.AccAddress) (sdk.Coin, bool) + CreateFlatFeeRewardsRecords(ctx sdk.Context, contractAddress sdk.AccAddress, flatfee sdk.Coin) + + // Used in DeductFeeDecorator + TxFeeRebateRatio(ctx sdk.Context) sdk.Dec + TrackFeeRebatesRewards(ctx sdk.Context, rewards sdk.Coins) +} + +func GetContractFlatFees(ctx sdk.Context, rk RewardsKeeperExpected, codec codec.BinaryCodec, m sdk.Msg) (fees sdk.Coins, hasWasmMsgs bool, err error) { + switch msg := m.(type) { + case *wasmTypes.MsgMigrateContract: + { + return nil, true, nil + } + case *wasmTypes.MsgExecuteContract: // if msg is contract execute, fetch flatfee for msg.Contract address + { + ca, err := sdk.AccAddressFromBech32(msg.Contract) + if err != nil { + return nil, true, err + } + fee, found := rk.GetFlatFee(ctx, ca) + if found { + rk.CreateFlatFeeRewardsRecords(ctx, ca, fee) + return sdk.NewCoins(fee), true, nil + } + } + case *authz.MsgExec: // if msg is authz msg, unwrap the msg and check if any are wasmTypes.MsgExecuteContract + { + var flatfees sdk.Coins + for _, v := range msg.Msgs { + var wrappedMsg sdk.Msg + err := codec.UnpackAny(v, &wrappedMsg) + if err != nil { + return nil, false, sdkErrors.Wrapf(sdkErrors.ErrUnauthorized, "error decoding authz messages") + } + fees, hasWasmMsgs, err := GetContractFlatFees(ctx, rk, codec, wrappedMsg) + if err != nil { + return nil, hasWasmMsgs, err + } + flatfees = flatfees.Add(fees...) + } + return flatfees, hasWasmMsgs, nil + } + } + return nil, false, nil +} diff --git a/x/rewards/ante/fee_deduction.go b/x/rewards/ante/fee_deduction.go index 60d752ca..3a9c3dc7 100644 --- a/x/rewards/ante/fee_deduction.go +++ b/x/rewards/ante/fee_deduction.go @@ -3,6 +3,7 @@ package ante import ( "fmt" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" sdkErrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/auth/ante" @@ -16,26 +17,22 @@ import ( var _ sdk.AnteDecorator = DeductFeeDecorator{} -// TxFeeRewardsKeeperExpected defines the expected interface for the x/rewards keeper. -type TxFeeRewardsKeeperExpected interface { - TxFeeRebateRatio(ctx sdk.Context) sdk.Dec - TrackFeeRebatesRewards(ctx sdk.Context, rewards sdk.Coins) -} - // DeductFeeDecorator deducts fees from the first signer of the tx. // If the first signer does not have the funds to pay for the fees, return with InsufficientFunds error. // Call next AnteHandler if fees successfully deducted. // CONTRACT: Tx must implement FeeTx interface to use DeductFeeDecorator. type DeductFeeDecorator struct { + codec codec.BinaryCodec ak ante.AccountKeeper bankKeeper authTypes.BankKeeper feegrantKeeper ante.FeegrantKeeper - rewardsKeeper TxFeeRewardsKeeperExpected + rewardsKeeper RewardsKeeperExpected } // NewDeductFeeDecorator returns a new DeductFeeDecorator instance. -func NewDeductFeeDecorator(ak ante.AccountKeeper, bk authTypes.BankKeeper, fk ante.FeegrantKeeper, rk TxFeeRewardsKeeperExpected) DeductFeeDecorator { +func NewDeductFeeDecorator(codec codec.BinaryCodec, ak ante.AccountKeeper, bk authTypes.BankKeeper, fk ante.FeegrantKeeper, rk RewardsKeeperExpected) DeductFeeDecorator { return DeductFeeDecorator{ + codec: codec, ak: ak, bankKeeper: bk, feegrantKeeper: fk, @@ -117,6 +114,19 @@ func (dfd DeductFeeDecorator) deductFees(ctx sdk.Context, tx sdk.Tx, acc authTyp } } + // var flatFees sdk.Coins + // for _, m := range tx.GetMsgs() { + // flatFees, _, err := GetContractFlatFees(ctx, dfd.rewardsKeeper, dfd.codec, m) + // if err != nil { + // return err + // } + // flatFees = flatFees.Add(flatFees...) + // } + + // if !flatFees.Empty() { + + // } + // Send everything to the fee collector account if rewards are disabled or transaction is not wasm related rebateRatio := dfd.rewardsKeeper.TxFeeRebateRatio(ctx) if rebateRatio.IsZero() || !hasWasmMsgs { diff --git a/x/rewards/ante/fee_deduction_test.go b/x/rewards/ante/fee_deduction_test.go index 0403958d..51925316 100644 --- a/x/rewards/ante/fee_deduction_test.go +++ b/x/rewards/ante/fee_deduction_test.go @@ -132,7 +132,7 @@ func TestRewardsFeeDeductionAnteHandler(t *testing.T) { ) // Call the deduction Ante handler manually - anteHandler := ante.NewDeductFeeDecorator(chain.GetApp().AccountKeeper, chain.GetApp().BankKeeper, chain.GetApp().FeeGrantKeeper, chain.GetApp().RewardsKeeper) + anteHandler := ante.NewDeductFeeDecorator(chain.GetAppCodec(), chain.GetApp().AccountKeeper, chain.GetApp().BankKeeper, chain.GetApp().FeeGrantKeeper, chain.GetApp().RewardsKeeper) _, err = anteHandler.AnteHandle(ctx, tx, false, testutils.NoopAnteHandler) if tc.errExpected { require.Error(t, err) diff --git a/x/rewards/ante/min_cons_fee.go b/x/rewards/ante/min_cons_fee.go index d7ed85c0..651bb077 100644 --- a/x/rewards/ante/min_cons_fee.go +++ b/x/rewards/ante/min_cons_fee.go @@ -1,33 +1,26 @@ package ante import ( - wasmTypes "github.com/CosmWasm/wasmd/x/wasm/types" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" sdkErrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/x/authz" + bankTypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/archway-network/archway/pkg" ) -// RewardsFeeReaderExpected defines the expected interface for the x/rewards keeper. -type RewardsFeeReaderExpected interface { - GetMinConsensusFee(ctx sdk.Context) (sdk.DecCoin, bool) - GetFlatFee(ctx sdk.Context, contractAddr sdk.AccAddress) (sdk.Coin, bool) - CreateFlatFeeRewardsRecords(ctx sdk.Context, contractAddress sdk.AccAddress, flatfee sdk.Coin) -} - // MinFeeDecorator rejects transaction if its fees are less than minimum fees defined by the x/rewards module. // Estimation is done using the minimum consensus fee value which is the minimum gas unit price. // The minimum consensus fee value is defined by block dApp rewards and rewards distribution parameters. // CONTRACT: Tx must implement FeeTx interface to use MinFeeDecorator. type MinFeeDecorator struct { codec codec.BinaryCodec - rewardsKeeper RewardsFeeReaderExpected + rewardsKeeper RewardsKeeperExpected + bankKeeper bankTypes.BankKeeper } // NewMinFeeDecorator returns a new MinFeeDecorator instance. -func NewMinFeeDecorator(codec codec.BinaryCodec, rk RewardsFeeReaderExpected) MinFeeDecorator { +func NewMinFeeDecorator(codec codec.BinaryCodec, rk RewardsKeeperExpected) MinFeeDecorator { return MinFeeDecorator{ codec: codec, rewardsKeeper: rk, @@ -64,7 +57,7 @@ func (mfd MinFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, // Get flatfees for any contracts being called in the tx.msgs for _, m := range tx.GetMsgs() { - flatFees, err := mfd.getContractFlatFees(ctx, m) + flatFees, _, err := GetContractFlatFees(ctx, mfd.rewardsKeeper, mfd.codec, m) if err != nil { return ctx, err } @@ -77,38 +70,3 @@ func (mfd MinFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, } return ctx, sdkErrors.Wrapf(sdkErrors.ErrInsufficientFee, "tx fee %s is less than min fee: %s", txFees, expectedFees.String()) } - -func (mfd MinFeeDecorator) getContractFlatFees(ctx sdk.Context, m sdk.Msg) (sdk.Coins, error) { - switch msg := m.(type) { - case *wasmTypes.MsgExecuteContract: // if msg is contract execute, fetch flatfee for msg.Contract address - { - ca, err := sdk.AccAddressFromBech32(msg.Contract) - if err != nil { - return nil, err - } - fee, found := mfd.rewardsKeeper.GetFlatFee(ctx, ca) - if found { - mfd.rewardsKeeper.CreateFlatFeeRewardsRecords(ctx, ca, fee) - return sdk.NewCoins(fee), nil - } - } - case *authz.MsgExec: // if msg is authz msg, unwrap the msg and check if any are wasmTypes.MsgExecuteContract - { - var flatfees sdk.Coins - for _, v := range msg.Msgs { - var wrappedMsg sdk.Msg - err := mfd.codec.UnpackAny(v, &wrappedMsg) - if err != nil { - return nil, sdkErrors.Wrapf(sdkErrors.ErrUnauthorized, "error decoding authz messages") - } - fees, err := mfd.getContractFlatFees(ctx, wrappedMsg) - if err != nil { - return nil, err - } - flatfees = flatfees.Add(fees...) - } - return flatfees, nil - } - } - return nil, nil -} From 3890175ba7cd5426761c21ced5e31a5beacea821 Mon Sep 17 00:00:00 2001 From: Spoorthi Satheesha <9302666+spoo-bar@users.noreply.github.com> Date: Fri, 14 Apr 2023 16:47:35 +0100 Subject: [PATCH 05/15] distribute flatfees --- x/rewards/ante/fee_deduction.go | 38 +++++++++++++-------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/x/rewards/ante/fee_deduction.go b/x/rewards/ante/fee_deduction.go index 3a9c3dc7..8d245f02 100644 --- a/x/rewards/ante/fee_deduction.go +++ b/x/rewards/ante/fee_deduction.go @@ -9,8 +9,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/ante" authTypes "github.com/cosmos/cosmos-sdk/x/auth/types" - wasmdTypes "github.com/CosmWasm/wasmd/x/wasm/types" - "github.com/archway-network/archway/pkg" rewardsTypes "github.com/archway-network/archway/x/rewards/types" ) @@ -100,33 +98,20 @@ func (dfd DeductFeeDecorator) deductFees(ctx sdk.Context, tx sdk.Tx, acc authTyp return sdkErrors.Wrapf(sdkErrors.ErrInsufficientFee, "invalid fee amount: %s", fees) } + var flatFees sdk.Coins // Check if transaction has wasmd operations hasWasmMsgs := false - for _, msg := range tx.GetMsgs() { - // We can use switch here, but breaking the for loop from switch is less readable - if _, ok := msg.(*wasmdTypes.MsgExecuteContract); ok { - hasWasmMsgs = true - break + for _, m := range tx.GetMsgs() { + flatFees, hwm, err := GetContractFlatFees(ctx, dfd.rewardsKeeper, dfd.codec, m) + if err != nil { + return err } - if _, ok := msg.(*wasmdTypes.MsgMigrateContract); ok { - hasWasmMsgs = true - break + if !hasWasmMsgs { + hasWasmMsgs = hwm //set hasWasmMsgs as true if its false. if its true, do nothing } + flatFees = flatFees.Add(flatFees...) } - // var flatFees sdk.Coins - // for _, m := range tx.GetMsgs() { - // flatFees, _, err := GetContractFlatFees(ctx, dfd.rewardsKeeper, dfd.codec, m) - // if err != nil { - // return err - // } - // flatFees = flatFees.Add(flatFees...) - // } - - // if !flatFees.Empty() { - - // } - // Send everything to the fee collector account if rewards are disabled or transaction is not wasm related rebateRatio := dfd.rewardsKeeper.TxFeeRebateRatio(ctx) if rebateRatio.IsZero() || !hasWasmMsgs { @@ -136,6 +121,13 @@ func (dfd DeductFeeDecorator) deductFees(ctx sdk.Context, tx sdk.Tx, acc authTyp return nil } + if !flatFees.Empty() { + if err := dfd.bankKeeper.SendCoinsFromAccountToModule(ctx, acc.GetAddress(), authTypes.FeeCollectorName, flatFees); err != nil { + return sdkErrors.Wrapf(sdkErrors.ErrInsufficientFunds, err.Error()) + } + fees = fees.Sub(flatFees) // reduce flatfees from the sent fees amount + } + // Split the fees between the fee collector account and the rewards collector account rewardsFees, authFees := pkg.SplitCoins(fees, rebateRatio) From 524e88528b073c7d61f91c050b930cdbb08d9f5f Mon Sep 17 00:00:00 2001 From: Spoorthi Satheesha <9302666+spoo-bar@users.noreply.github.com> Date: Fri, 14 Apr 2023 17:06:04 +0100 Subject: [PATCH 06/15] fixing tests --- x/rewards/ante/ante_utils.go | 1 + x/rewards/ante/fee_deduction.go | 4 ++-- x/rewards/ante/fee_deduction_test.go | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/x/rewards/ante/ante_utils.go b/x/rewards/ante/ante_utils.go index 02d29c1e..3e8fc21a 100644 --- a/x/rewards/ante/ante_utils.go +++ b/x/rewards/ante/ante_utils.go @@ -37,6 +37,7 @@ func GetContractFlatFees(ctx sdk.Context, rk RewardsKeeperExpected, codec codec. rk.CreateFlatFeeRewardsRecords(ctx, ca, fee) return sdk.NewCoins(fee), true, nil } + return nil, true, nil } case *authz.MsgExec: // if msg is authz msg, unwrap the msg and check if any are wasmTypes.MsgExecuteContract { diff --git a/x/rewards/ante/fee_deduction.go b/x/rewards/ante/fee_deduction.go index 8d245f02..b60ee46f 100644 --- a/x/rewards/ante/fee_deduction.go +++ b/x/rewards/ante/fee_deduction.go @@ -102,14 +102,14 @@ func (dfd DeductFeeDecorator) deductFees(ctx sdk.Context, tx sdk.Tx, acc authTyp // Check if transaction has wasmd operations hasWasmMsgs := false for _, m := range tx.GetMsgs() { - flatFees, hwm, err := GetContractFlatFees(ctx, dfd.rewardsKeeper, dfd.codec, m) + fees, hwm, err := GetContractFlatFees(ctx, dfd.rewardsKeeper, dfd.codec, m) if err != nil { return err } if !hasWasmMsgs { hasWasmMsgs = hwm //set hasWasmMsgs as true if its false. if its true, do nothing } - flatFees = flatFees.Add(flatFees...) + flatFees = flatFees.Add(fees...) } // Send everything to the fee collector account if rewards are disabled or transaction is not wasm related diff --git a/x/rewards/ante/fee_deduction_test.go b/x/rewards/ante/fee_deduction_test.go index 51925316..9384d7c2 100644 --- a/x/rewards/ante/fee_deduction_test.go +++ b/x/rewards/ante/fee_deduction_test.go @@ -30,7 +30,9 @@ func TestRewardsFeeDeductionAnteHandler(t *testing.T) { rewardsBalanceDiffExpected string // expected x/rewards module balance diff [sdk.Coins] } - mockWasmExecuteMsg := &wasmdTypes.MsgExecuteContract{} + mockWasmExecuteMsg := &wasmdTypes.MsgExecuteContract{ + Contract: e2eTesting.GenContractAddresses(1)[0].String(), + } newStakeCoin := func(amt uint64) sdk.Coin { return sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewIntFromUint64(amt)) From 0d0a925a9d02d0a6ffd45ae62bdf9f8c447f719f Mon Sep 17 00:00:00 2001 From: Spoorthi Satheesha <9302666+spoo-bar@users.noreply.github.com> Date: Fri, 14 Apr 2023 17:17:46 +0100 Subject: [PATCH 07/15] fix lint error --- x/rewards/ante/min_cons_fee.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/x/rewards/ante/min_cons_fee.go b/x/rewards/ante/min_cons_fee.go index 651bb077..97f9a215 100644 --- a/x/rewards/ante/min_cons_fee.go +++ b/x/rewards/ante/min_cons_fee.go @@ -4,7 +4,6 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" sdkErrors "github.com/cosmos/cosmos-sdk/types/errors" - bankTypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/archway-network/archway/pkg" ) @@ -16,7 +15,6 @@ import ( type MinFeeDecorator struct { codec codec.BinaryCodec rewardsKeeper RewardsKeeperExpected - bankKeeper bankTypes.BankKeeper } // NewMinFeeDecorator returns a new MinFeeDecorator instance. From b8aa72d37cbbd73837580110bdfd2953b2dcc872 Mon Sep 17 00:00:00 2001 From: Spoorthi Satheesha <9302666+spoo-bar@users.noreply.github.com> Date: Mon, 17 Apr 2023 17:55:36 +0100 Subject: [PATCH 08/15] refactoring some more --- x/rewards/ante/ante_utils.go | 20 ++++++++++++-------- x/rewards/ante/fee_deduction.go | 8 +++++--- x/rewards/ante/min_cons_fee.go | 7 +++++-- x/rewards/keeper/flat_fee.go | 4 ++-- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/x/rewards/ante/ante_utils.go b/x/rewards/ante/ante_utils.go index 3e8fc21a..ba47b9a0 100644 --- a/x/rewards/ante/ante_utils.go +++ b/x/rewards/ante/ante_utils.go @@ -13,14 +13,19 @@ type RewardsKeeperExpected interface { // Used in MinFeeDecorator GetMinConsensusFee(ctx sdk.Context) (sdk.DecCoin, bool) GetFlatFee(ctx sdk.Context, contractAddr sdk.AccAddress) (sdk.Coin, bool) - CreateFlatFeeRewardsRecords(ctx sdk.Context, contractAddress sdk.AccAddress, flatfee sdk.Coin) + CreateFlatFeeRewardsRecords(ctx sdk.Context, contractAddress sdk.AccAddress, flatfee sdk.Coins) // Used in DeductFeeDecorator TxFeeRebateRatio(ctx sdk.Context) sdk.Dec TrackFeeRebatesRewards(ctx sdk.Context, rewards sdk.Coins) } -func GetContractFlatFees(ctx sdk.Context, rk RewardsKeeperExpected, codec codec.BinaryCodec, m sdk.Msg) (fees sdk.Coins, hasWasmMsgs bool, err error) { +type contractFlatFee struct { + ContractAddress sdk.AccAddress + FlatFees sdk.Coins +} + +func GetContractFlatFees(ctx sdk.Context, rk RewardsKeeperExpected, codec codec.BinaryCodec, m sdk.Msg) (contractFlatFees []contractFlatFee, hasWasmMsgs bool, err error) { switch msg := m.(type) { case *wasmTypes.MsgMigrateContract: { @@ -34,27 +39,26 @@ func GetContractFlatFees(ctx sdk.Context, rk RewardsKeeperExpected, codec codec. } fee, found := rk.GetFlatFee(ctx, ca) if found { - rk.CreateFlatFeeRewardsRecords(ctx, ca, fee) - return sdk.NewCoins(fee), true, nil + contractFlatFees = append(contractFlatFees, contractFlatFee{ContractAddress: ca, FlatFees: sdk.NewCoins(fee)}) + return contractFlatFees, true, nil } return nil, true, nil } case *authz.MsgExec: // if msg is authz msg, unwrap the msg and check if any are wasmTypes.MsgExecuteContract { - var flatfees sdk.Coins for _, v := range msg.Msgs { var wrappedMsg sdk.Msg err := codec.UnpackAny(v, &wrappedMsg) if err != nil { return nil, false, sdkErrors.Wrapf(sdkErrors.ErrUnauthorized, "error decoding authz messages") } - fees, hasWasmMsgs, err := GetContractFlatFees(ctx, rk, codec, wrappedMsg) + cff, hasWasmMsgs, err := GetContractFlatFees(ctx, rk, codec, wrappedMsg) if err != nil { return nil, hasWasmMsgs, err } - flatfees = flatfees.Add(fees...) + contractFlatFees = append(contractFlatFees, cff...) } - return flatfees, hasWasmMsgs, nil + return contractFlatFees, hasWasmMsgs, nil } } return nil, false, nil diff --git a/x/rewards/ante/fee_deduction.go b/x/rewards/ante/fee_deduction.go index b60ee46f..e69c5a40 100644 --- a/x/rewards/ante/fee_deduction.go +++ b/x/rewards/ante/fee_deduction.go @@ -102,14 +102,16 @@ func (dfd DeductFeeDecorator) deductFees(ctx sdk.Context, tx sdk.Tx, acc authTyp // Check if transaction has wasmd operations hasWasmMsgs := false for _, m := range tx.GetMsgs() { - fees, hwm, err := GetContractFlatFees(ctx, dfd.rewardsKeeper, dfd.codec, m) + contractFlatFees, hwm, err := GetContractFlatFees(ctx, dfd.rewardsKeeper, dfd.codec, m) if err != nil { return err } if !hasWasmMsgs { hasWasmMsgs = hwm //set hasWasmMsgs as true if its false. if its true, do nothing } - flatFees = flatFees.Add(fees...) + for _, cff := range contractFlatFees { + flatFees = flatFees.Add(cff.FlatFees...) + } } // Send everything to the fee collector account if rewards are disabled or transaction is not wasm related @@ -122,7 +124,7 @@ func (dfd DeductFeeDecorator) deductFees(ctx sdk.Context, tx sdk.Tx, acc authTyp } if !flatFees.Empty() { - if err := dfd.bankKeeper.SendCoinsFromAccountToModule(ctx, acc.GetAddress(), authTypes.FeeCollectorName, flatFees); err != nil { + if err := dfd.bankKeeper.SendCoinsFromAccountToModule(ctx, acc.GetAddress(), rewardsTypes.ContractRewardCollector, flatFees); err != nil { return sdkErrors.Wrapf(sdkErrors.ErrInsufficientFunds, err.Error()) } fees = fees.Sub(flatFees) // reduce flatfees from the sent fees amount diff --git a/x/rewards/ante/min_cons_fee.go b/x/rewards/ante/min_cons_fee.go index 97f9a215..a5fca060 100644 --- a/x/rewards/ante/min_cons_fee.go +++ b/x/rewards/ante/min_cons_fee.go @@ -55,11 +55,14 @@ func (mfd MinFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, // Get flatfees for any contracts being called in the tx.msgs for _, m := range tx.GetMsgs() { - flatFees, _, err := GetContractFlatFees(ctx, mfd.rewardsKeeper, mfd.codec, m) + contractFlatFees, _, err := GetContractFlatFees(ctx, mfd.rewardsKeeper, mfd.codec, m) if err != nil { return ctx, err } - expectedFees = expectedFees.Add(flatFees...) + for _, cff := range contractFlatFees { + mfd.rewardsKeeper.CreateFlatFeeRewardsRecords(ctx, cff.ContractAddress, cff.FlatFees) + expectedFees = expectedFees.Add(cff.FlatFees...) + } } txFees := feeTx.GetFee() diff --git a/x/rewards/keeper/flat_fee.go b/x/rewards/keeper/flat_fee.go index d557e9de..bdd6245b 100644 --- a/x/rewards/keeper/flat_fee.go +++ b/x/rewards/keeper/flat_fee.go @@ -42,12 +42,12 @@ func (k Keeper) GetFlatFee(ctx sdk.Context, contractAddr sdk.AccAddress) (sdk.Co return fee, true } -func (k Keeper) CreateFlatFeeRewardsRecords(ctx sdk.Context, contractAddress sdk.AccAddress, flatfee sdk.Coin) { +func (k Keeper) CreateFlatFeeRewardsRecords(ctx sdk.Context, contractAddress sdk.AccAddress, flatfees sdk.Coins) { rewardsRecordState := k.state.RewardsRecord(ctx) calculationHeight, calculationTime := ctx.BlockHeight(), ctx.BlockTime() metadata := k.GetContractMetadata(ctx, contractAddress) rewardsAddr := sdk.MustAccAddressFromBech32(metadata.RewardsAddress) - rewardsRecordState.CreateRewardsRecord(rewardsAddr, sdk.NewCoins(flatfee), calculationHeight, calculationTime) + rewardsRecordState.CreateRewardsRecord(rewardsAddr, flatfees, calculationHeight, calculationTime) } From 9629e47f92d31e18a84cbcc5387531ad4911db52 Mon Sep 17 00:00:00 2001 From: Spoorthi Satheesha <9302666+spoo-bar@users.noreply.github.com> Date: Mon, 17 Apr 2023 18:36:10 +0100 Subject: [PATCH 09/15] fixing tests --- e2e/rewards_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/e2e/rewards_test.go b/e2e/rewards_test.go index e4efeecf..0f5d75dc 100644 --- a/e2e/rewards_test.go +++ b/e2e/rewards_test.go @@ -414,9 +414,10 @@ func (s *E2ETestSuite) TestTXFailsAfterAnteHandler() { RewardsAddress: contractAddr.String(), }) + flatFees := sdk.NewInt64Coin("stake", 1000) err := rewardsKeeper.SetFlatFee(chain.GetContext(), senderAcc.Address, rewardsTypes.FlatFee{ ContractAddress: contractAddr.String(), - FlatFee: sdk.NewInt64Coin("stake", 1000), + FlatFee: flatFees, }) require.NoError(s.T(), err) @@ -446,7 +447,6 @@ func (s *E2ETestSuite) TestTXFailsAfterAnteHandler() { return } - rk := chain.GetApp().RewardsKeeper // send a message that passes the ante handler but not the wasm execution step sendMsg(&wasmdTypes.MsgExecuteContract{ @@ -459,8 +459,8 @@ func (s *E2ETestSuite) TestTXFailsAfterAnteHandler() { chain.NextBlock(1 * time.Second) // no rewards because the TX failed. - rewards := rk.GetState().RewardsRecord(chain.GetContext()).GetRewardsRecordByRewardsAddress(contractAddr) - require.Empty(s.T(), rewards) + rewards := rewardsKeeper.GetState().RewardsRecord(chain.GetContext()).GetRewardsRecordByRewardsAddress(contractAddr) + require.Equal(s.T(), flatFees, rewards[0].Rewards[0]) } // TestSubMsgRevert tests when a contract calls another contract but the sub message reverts, From 7dcca73f529917a04c0eb911456ee819a5d82fde Mon Sep 17 00:00:00 2001 From: Spoorthi Satheesha <9302666+spoo-bar@users.noreply.github.com> Date: Tue, 18 Apr 2023 10:43:43 +0100 Subject: [PATCH 10/15] adding rewards flatfees test --- e2e/rewards_test.go | 102 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/e2e/rewards_test.go b/e2e/rewards_test.go index 0f5d75dc..c2ce784d 100644 --- a/e2e/rewards_test.go +++ b/e2e/rewards_test.go @@ -463,6 +463,108 @@ func (s *E2ETestSuite) TestTXFailsAfterAnteHandler() { require.Equal(s.T(), flatFees, rewards[0].Rewards[0]) } +// TestRewardsFlatFees tests that a contract which has flatfees set, on a successful execution against +// the contract the relevant rewards records have been created +func (s *E2ETestSuite) TestRewardsFlatFees() { + // Create a custom chain with "close to mainnet" params + chain := e2eTesting.NewTestChain(s.T(), 1, + // Set 1B total supply (10^9 * 10^6) + e2eTesting.WithGenAccounts(1), + e2eTesting.WithGenDefaultCoinBalance("1000000000000000"), + // Set bonded ratio to 30% + e2eTesting.WithBondAmount("300000000000000"), + // Override the default Tx fee + e2eTesting.WithDefaultFeeAmount("10000000"), + // Set block gas limit (Archway mainnet param) + e2eTesting.WithBlockGasLimit(100_000_000), + // x/rewards distribution params + e2eTesting.WithTxFeeRebatesRewardsRatio(sdk.NewDecWithPrec(5, 1)), + e2eTesting.WithInflationRewardsRatio(sdk.NewDecWithPrec(2, 1)), + // Set constant inflation rate + e2eTesting.WithMintParams( + sdk.NewDecWithPrec(10, 2), // 10% + sdk.NewDecWithPrec(10, 2), // 10% + uint64(60*60*8766/1), // 1 seconds block time + ), + ) + rewardsKeeper := chain.GetApp().RewardsKeeper + + // Upload a new contract and set its address as the rewardsAddress + senderAcc := chain.GetAccount(0) + contractAddr := s.VoterUploadAndInstantiate(chain, senderAcc) + + // Setting contract metadata with rewards address to be itself + chain.SetContractMetadata(senderAcc, contractAddr, rewardsTypes.ContractMetadata{ + ContractAddress: contractAddr.String(), + OwnerAddress: senderAcc.Address.String(), + RewardsAddress: contractAddr.String(), + }) + + // Setting contract flatfee to be 1000 stake + flatFees := sdk.NewInt64Coin("stake", 1000) + err := rewardsKeeper.SetFlatFee(chain.GetContext(), senderAcc.Address, rewardsTypes.FlatFee{ + ContractAddress: contractAddr.String(), + FlatFee: flatFees, + }) + require.NoError(s.T(), err) + + // contract execution to trigger rewards distribution + req := voterTypes.MsgExecute{ + NewVoting: &voterTypes.NewVotingRequest{ + Name: "Test", + VoteOptions: []string{"Yes", "No"}, + Duration: uint64(time.Minute), + }, + } + reqBz, err := req.MarshalJSON() + s.Require().NoError(err) + msg := wasmdTypes.MsgExecuteContract{ + Sender: senderAcc.Address.String(), + Contract: contractAddr.String(), + Msg: reqBz, + Funds: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, DefNewVotingCostAmt)), + } + _, _, _, err = chain.SendMsgs(senderAcc, true, []sdk.Msg{&msg}) + require.NoError(s.T(), err) + + chain.NextBlock(1 * time.Second) + + // should find two rewards records + // 1. Flatfee rewards record + // 2. InflationaryRewards + FeeRewards rewards record + rewards := rewardsKeeper.GetState().RewardsRecord(chain.GetContext()).GetRewardsRecordByRewardsAddress(contractAddr) + require.Len(s.T(), rewards, 2) + require.Equal(s.T(), flatFees, rewards[0].Rewards[0]) // the first rewards record matches our set flat fees + + // Lets now do the same operations a bunch of times - and by a bunch of times i mean ten times + // this should generate quite a few rewards records + // each msg execute is in seperate block + for i := 0; i < 10; i++ { + // contract execution to trigger rewards distribution + req := voterTypes.MsgExecute{ + NewVoting: &voterTypes.NewVotingRequest{ + Name: "Test", + VoteOptions: []string{"Yes", "No"}, + Duration: uint64(time.Minute), + }, + } + reqBz, err := req.MarshalJSON() + s.Require().NoError(err) + msg := wasmdTypes.MsgExecuteContract{ + Sender: senderAcc.Address.String(), + Contract: contractAddr.String(), + Msg: reqBz, + Funds: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, DefNewVotingCostAmt)), + } + _, _, _, err = chain.SendMsgs(senderAcc, true, []sdk.Msg{&msg}) + require.NoError(s.T(), err) + + chain.NextBlock(1 * time.Second) + } + rewards = rewardsKeeper.GetState().RewardsRecord(chain.GetContext()).GetRewardsRecordByRewardsAddress(contractAddr) + require.Len(s.T(), rewards, 22) // why 22? cuz we already had 2 rewards record. we made 10txs now. and each tx creates two records. so 2 + (10 * 2) = 22 +} + // TestSubMsgRevert tests when a contract calls another contract but the sub message reverts, // and the execution of the caller contract still proceeds because the sub message is sent with // a reply on error flag. From 90e2e1c9e062943e836c709f0ec5e2dca80b5a87 Mon Sep 17 00:00:00 2001 From: Spoorthi Satheesha <9302666+spoo-bar@users.noreply.github.com> Date: Tue, 18 Apr 2023 10:46:17 +0100 Subject: [PATCH 11/15] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1a480a8..9bcc02cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,12 @@ Contains bug fixes. Contains all the PRs that improved the code without changing the behaviours. --> +## [Unreleased] + +### Fixed + +- [#338](https://github.com/archway-network/archway/pull/338) - fixed issue where contract premium was not completly being sent to the rewards address + ## [v0.3.1] ### Fixed From a7dca89979472764c9f6ca2e2183d3ad94a20d38 Mon Sep 17 00:00:00 2001 From: Spoorthi Satheesha <9302666+spoo-bar@users.noreply.github.com> Date: Tue, 18 Apr 2023 10:56:40 +0100 Subject: [PATCH 12/15] adding func comments --- e2e/rewards_test.go | 2 +- x/rewards/keeper/flat_fee.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/e2e/rewards_test.go b/e2e/rewards_test.go index c2ce784d..508e2af9 100644 --- a/e2e/rewards_test.go +++ b/e2e/rewards_test.go @@ -538,7 +538,7 @@ func (s *E2ETestSuite) TestRewardsFlatFees() { // Lets now do the same operations a bunch of times - and by a bunch of times i mean ten times // this should generate quite a few rewards records - // each msg execute is in seperate block + // each msg execute is in separate block for i := 0; i < 10; i++ { // contract execution to trigger rewards distribution req := voterTypes.MsgExecute{ diff --git a/x/rewards/keeper/flat_fee.go b/x/rewards/keeper/flat_fee.go index bdd6245b..b193094d 100644 --- a/x/rewards/keeper/flat_fee.go +++ b/x/rewards/keeper/flat_fee.go @@ -42,6 +42,7 @@ func (k Keeper) GetFlatFee(ctx sdk.Context, contractAddr sdk.AccAddress) (sdk.Co return fee, true } +// CreateFlatFeeRewardsRecords creates a rewards record for the flatfees of the given contract func (k Keeper) CreateFlatFeeRewardsRecords(ctx sdk.Context, contractAddress sdk.AccAddress, flatfees sdk.Coins) { rewardsRecordState := k.state.RewardsRecord(ctx) calculationHeight, calculationTime := ctx.BlockHeight(), ctx.BlockTime() From a463ed98ba67491fe413ab0a3d87d28a4f06cf8b Mon Sep 17 00:00:00 2001 From: Spoorthi Satheesha <9302666+spoo-bar@users.noreply.github.com> Date: Wed, 19 Apr 2023 15:27:48 +0100 Subject: [PATCH 13/15] adding a require to test contract exec fail creates only one rewards record --- e2e/rewards_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/e2e/rewards_test.go b/e2e/rewards_test.go index 508e2af9..eefcda97 100644 --- a/e2e/rewards_test.go +++ b/e2e/rewards_test.go @@ -460,6 +460,7 @@ func (s *E2ETestSuite) TestTXFailsAfterAnteHandler() { // no rewards because the TX failed. rewards := rewardsKeeper.GetState().RewardsRecord(chain.GetContext()).GetRewardsRecordByRewardsAddress(contractAddr) + require.Len(s.T(), rewards, 1) require.Equal(s.T(), flatFees, rewards[0].Rewards[0]) } From 2af0dcde8c1c54f022333bf17239b95ffb8adabe Mon Sep 17 00:00:00 2001 From: Spoorthi Satheesha <9302666+spoo-bar@users.noreply.github.com> Date: Wed, 19 Apr 2023 15:28:37 +0100 Subject: [PATCH 14/15] updating test case code comment --- e2e/rewards_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/rewards_test.go b/e2e/rewards_test.go index eefcda97..94e8f35f 100644 --- a/e2e/rewards_test.go +++ b/e2e/rewards_test.go @@ -458,7 +458,7 @@ func (s *E2ETestSuite) TestTXFailsAfterAnteHandler() { chain.NextBlock(1 * time.Second) - // no rewards because the TX failed. + // only rewards record for contract premiums. no rewards record for feerebaes/inflation because because the TX failed. rewards := rewardsKeeper.GetState().RewardsRecord(chain.GetContext()).GetRewardsRecordByRewardsAddress(contractAddr) require.Len(s.T(), rewards, 1) require.Equal(s.T(), flatFees, rewards[0].Rewards[0]) From a6cd05d8eae387f3349931fa10f5e9229ebc0a68 Mon Sep 17 00:00:00 2001 From: Spoorthi Satheesha <9302666+spoo-bar@users.noreply.github.com> Date: Wed, 19 Apr 2023 17:10:46 +0100 Subject: [PATCH 15/15] adding second contract to contract premium e2e test --- e2e/rewards_test.go | 76 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 17 deletions(-) diff --git a/e2e/rewards_test.go b/e2e/rewards_test.go index 94e8f35f..231d4e0e 100644 --- a/e2e/rewards_test.go +++ b/e2e/rewards_test.go @@ -470,7 +470,7 @@ func (s *E2ETestSuite) TestRewardsFlatFees() { // Create a custom chain with "close to mainnet" params chain := e2eTesting.NewTestChain(s.T(), 1, // Set 1B total supply (10^9 * 10^6) - e2eTesting.WithGenAccounts(1), + e2eTesting.WithGenAccounts(2), e2eTesting.WithGenDefaultCoinBalance("1000000000000000"), // Set bonded ratio to 30% e2eTesting.WithBondAmount("300000000000000"), @@ -519,6 +519,7 @@ func (s *E2ETestSuite) TestRewardsFlatFees() { } reqBz, err := req.MarshalJSON() s.Require().NoError(err) + msg := wasmdTypes.MsgExecuteContract{ Sender: senderAcc.Address.String(), Contract: contractAddr.String(), @@ -536,34 +537,75 @@ func (s *E2ETestSuite) TestRewardsFlatFees() { rewards := rewardsKeeper.GetState().RewardsRecord(chain.GetContext()).GetRewardsRecordByRewardsAddress(contractAddr) require.Len(s.T(), rewards, 2) require.Equal(s.T(), flatFees, rewards[0].Rewards[0]) // the first rewards record matches our set flat fees + require.Equal(s.T(), sdk.NewInt64Coin("stake", 4999724), rewards[1].Rewards[0]) + + // Setting up a second contract which also has flat fees enabled + sender2Acc := chain.GetAccount(1) + contract2Addr := s.VoterUploadAndInstantiate(chain, sender2Acc) + chain.SetContractMetadata(sender2Acc, contract2Addr, rewardsTypes.ContractMetadata{ + ContractAddress: contract2Addr.String(), + OwnerAddress: sender2Acc.Address.String(), + RewardsAddress: contract2Addr.String(), + }) + flatFees2 := sdk.NewInt64Coin("stake", 20) + err = rewardsKeeper.SetFlatFee(chain.GetContext(), sender2Acc.Address, rewardsTypes.FlatFee{ + ContractAddress: contract2Addr.String(), + FlatFee: flatFees2, + }) + require.NoError(s.T(), err) // Lets now do the same operations a bunch of times - and by a bunch of times i mean ten times - // this should generate quite a few rewards records - // each msg execute is in separate block + // this should generate quite a few rewards records - and by quite a few i mean 50 times + // each loop the following are executed + // 1. execute contract1 and move to next block + // 2. execute contract2 and move to next block + // 3. execute contract1,contract1(again),contarct2 in a single msg and move to the next block for i := 0; i < 10; i++ { - // contract execution to trigger rewards distribution - req := voterTypes.MsgExecute{ - NewVoting: &voterTypes.NewVotingRequest{ - Name: "Test", - VoteOptions: []string{"Yes", "No"}, - Duration: uint64(time.Minute), - }, - } - reqBz, err := req.MarshalJSON() - s.Require().NoError(err) - msg := wasmdTypes.MsgExecuteContract{ + // execute contract1 and move to next block + _, _, _, err = chain.SendMsgs(senderAcc, true, []sdk.Msg{&wasmdTypes.MsgExecuteContract{ Sender: senderAcc.Address.String(), Contract: contractAddr.String(), Msg: reqBz, Funds: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, DefNewVotingCostAmt)), - } - _, _, _, err = chain.SendMsgs(senderAcc, true, []sdk.Msg{&msg}) + }}) + require.NoError(s.T(), err) + chain.NextBlock(1 * time.Second) + + // execute contract2 and move to next block + _, _, _, err = chain.SendMsgs(sender2Acc, true, []sdk.Msg{&wasmdTypes.MsgExecuteContract{ + Sender: sender2Acc.Address.String(), + Contract: contract2Addr.String(), + Msg: reqBz, + Funds: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, DefNewVotingCostAmt)), + }}) require.NoError(s.T(), err) + chain.NextBlock(1 * time.Second) + // execute contract1,contract1(again),contarct2 in a single msg and move to the next block + _, _, _, err = chain.SendMsgs(senderAcc, true, []sdk.Msg{&wasmdTypes.MsgExecuteContract{ + Sender: senderAcc.Address.String(), + Contract: contractAddr.String(), + Msg: reqBz, + Funds: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, DefNewVotingCostAmt)), + }, &wasmdTypes.MsgExecuteContract{ + Sender: senderAcc.Address.String(), + Contract: contractAddr.String(), + Msg: reqBz, + Funds: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, DefNewVotingCostAmt)), + }, &wasmdTypes.MsgExecuteContract{ + Sender: senderAcc.Address.String(), + Contract: contract2Addr.String(), + Msg: reqBz, + Funds: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, DefNewVotingCostAmt)), + }}) + require.NoError(s.T(), err) chain.NextBlock(1 * time.Second) } rewards = rewardsKeeper.GetState().RewardsRecord(chain.GetContext()).GetRewardsRecordByRewardsAddress(contractAddr) - require.Len(s.T(), rewards, 22) // why 22? cuz we already had 2 rewards record. we made 10txs now. and each tx creates two records. so 2 + (10 * 2) = 22 + require.Len(s.T(), rewards, 52) // why 52? cuz we already had 2 rewards record. we made 10 loops with 2 txs for this contract. And second txs contains 2 msgs. so 2 + (10 * (2 + 3)) = 52 + + rewards = rewardsKeeper.GetState().RewardsRecord(chain.GetContext()).GetRewardsRecordByRewardsAddress(contract2Addr) + require.Len(s.T(), rewards, 40) // why 40? cuz we made 10 loops with 2 txs for this contract. and each msg creates two records. so 10 * 2 * 2 = 40 } // TestSubMsgRevert tests when a contract calls another contract but the sub message reverts,