diff --git a/app/app_test/test_helpers.go b/app/app_test/test_helpers.go index ad6ac4fe..45db26bc 100644 --- a/app/app_test/test_helpers.go +++ b/app/app_test/test_helpers.go @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/suite" terra_app "github.com/terra-money/core/v2/app" appparams "github.com/terra-money/core/v2/app/params" + feeburntypes "github.com/terra-money/core/v2/x/feeburn/types" feesharetypes "github.com/terra-money/core/v2/x/feeshare/types" tokenfactorytypes "github.com/terra-money/core/v2/x/tokenfactory/types" @@ -80,6 +81,9 @@ func (s *AppTestSuite) Setup() { err = s.App.Keepers.TokenFactoryKeeper.SetParams(s.Ctx, tokenfactorytypes.DefaultParams()) s.Require().NoError(err) + err = s.App.Keepers.FeeBurnKeeper.SetParams(s.Ctx, feeburntypes.DefaultParams()) + s.Require().NoError(err) + err = s.FundModule(authtypes.FeeCollectorName, sdk.NewCoins(sdk.NewCoin("uluna", sdk.NewInt(1000)), sdk.NewCoin("utoken", sdk.NewInt(500)))) s.Require().NoError(err) diff --git a/app/genesis_test.go b/app/genesis_test.go index 45a2f7f7..c9823629 100644 --- a/app/genesis_test.go +++ b/app/genesis_test.go @@ -104,6 +104,11 @@ func TestGenesis(t *testing.T) { "evidence": { "evidence": [] }, + "feeburn": { + "params": { + "enable_fee_burn": true + } + }, "feegrant": { "allowances": [] }, diff --git a/integration-tests/package-lock.json b/integration-tests/package-lock.json index 95aa77bd..238bbd43 100644 --- a/integration-tests/package-lock.json +++ b/integration-tests/package-lock.json @@ -9,7 +9,7 @@ "version": "v2.9.0", "license": "MIT", "dependencies": { - "@terra-money/feather.js": "^2.0.0-beta.15", + "@terra-money/feather.js": "^2.0.0-beta.16", "moment": "^2.29.4" }, "devDependencies": { @@ -1802,9 +1802,9 @@ } }, "node_modules/@terra-money/feather.js": { - "version": "2.0.0-beta.15", - "resolved": "https://registry.npmjs.org/@terra-money/feather.js/-/feather.js-2.0.0-beta.15.tgz", - "integrity": "sha512-EDCGUAbIRedk8233gwshE1DF8nRtV7SUF390vDsAwozuRGHSXtZzDzB8SkdHlF8tDOz3ZEj/99aCuUVy2k5MiQ==", + "version": "2.0.0-beta.16", + "resolved": "https://registry.npmjs.org/@terra-money/feather.js/-/feather.js-2.0.0-beta.16.tgz", + "integrity": "sha512-VsIcHXft1T57HlWnyKfTIjylss15PZhMuIVjQ8hE7CJvI2p2/EEolGwLkOg/4EdzGJ2pSxGUGjvm97pGQAZERw==", "dependencies": { "@ethersproject/bytes": "^5.7.0", "@terra-money/legacy.proto": "npm:@terra-money/terra.proto@^0.1.7", @@ -7007,9 +7007,9 @@ } }, "@terra-money/feather.js": { - "version": "2.0.0-beta.15", - "resolved": "https://registry.npmjs.org/@terra-money/feather.js/-/feather.js-2.0.0-beta.15.tgz", - "integrity": "sha512-EDCGUAbIRedk8233gwshE1DF8nRtV7SUF390vDsAwozuRGHSXtZzDzB8SkdHlF8tDOz3ZEj/99aCuUVy2k5MiQ==", + "version": "2.0.0-beta.16", + "resolved": "https://registry.npmjs.org/@terra-money/feather.js/-/feather.js-2.0.0-beta.16.tgz", + "integrity": "sha512-VsIcHXft1T57HlWnyKfTIjylss15PZhMuIVjQ8hE7CJvI2p2/EEolGwLkOg/4EdzGJ2pSxGUGjvm97pGQAZERw==", "requires": { "@ethersproject/bytes": "^5.7.0", "@terra-money/legacy.proto": "npm:@terra-money/terra.proto@^0.1.7", diff --git a/integration-tests/package.json b/integration-tests/package.json index b3812a75..7242836b 100644 --- a/integration-tests/package.json +++ b/integration-tests/package.json @@ -35,7 +35,7 @@ "typescript": "^5.2.2" }, "dependencies": { - "@terra-money/feather.js": "^2.0.0-beta.15", + "@terra-money/feather.js": "^2.0.0-beta.16", "moment": "^2.29.4" } } diff --git a/integration-tests/src/modules/feeburn/feeburn.test.ts b/integration-tests/src/modules/feeburn/feeburn.test.ts new file mode 100644 index 00000000..86e182db --- /dev/null +++ b/integration-tests/src/modules/feeburn/feeburn.test.ts @@ -0,0 +1,57 @@ +import { Coins, Fee, MnemonicKey, MsgSend } from "@terra-money/feather.js"; +import { getMnemonics, getLCDClient, blockInclusion } from "../../helpers"; + +describe("FeeBurn Module (https://github.com/terra-money/core/tree/release/v2.9/x/feeburn) ", () => { + // Prepare environment clients, accounts and wallets + const LCD = getLCDClient(); + const accounts = getMnemonics(); + const wallet = LCD.chain1.wallet(accounts.mnemonic2); + const randomAddress = new MnemonicKey().accAddress("terra"); + + test('Must burn unused TX Fees', async () => { + try { + const sendTx = await wallet.createAndSignTx({ + msgs: [new MsgSend( + wallet.key.accAddress("terra"), + randomAddress, + new Coins({ uluna: 1 }), + )], + chainID: "test-1", + fee: new Fee(200_000, new Coins({ uluna: 3_000 })), + }); + + const result = await LCD.chain1.tx.broadcastSync(sendTx, "test-1"); + await blockInclusion(); + const txResult = await LCD.chain1.tx.txInfo(result.txhash, "test-1"); + const eventsLength = txResult.events.length; + expect([txResult.events[eventsLength - 2], txResult.events[eventsLength - 1]]) + .toStrictEqual([{ + "type": "burn", + "attributes": [{ + "key": "burner", + "value": "terra17xpfvakm2amg962yls6f84z3kell8c5lkaeqfa", + "index": true + }, { + "key": "amount", + "value": "1231uluna", + "index": true + }] + }, { + "type": "terra.feeburn.v1.FeeBurnEvent", + "attributes": [{ + "key": "burn_rate", + "value": "\"0.410385000000000000\"", + "index": true + }, { + "key": "fees_burn", + "value": "[{\"denom\":\"uluna\",\"amount\":\"1231\"}]", + "index": true + }] + }]); + + } + catch (e) { + console.log(e) + } + }); +}); \ No newline at end of file diff --git a/integration-tests/src/modules/pob/pob.test.ts b/integration-tests/src/modules/pob/pob.ts similarity index 100% rename from integration-tests/src/modules/pob/pob.test.ts rename to integration-tests/src/modules/pob/pob.ts diff --git a/proto/terra/feeburn/v1/events.proto b/proto/terra/feeburn/v1/events.proto index 349297ad..e76ed35a 100644 --- a/proto/terra/feeburn/v1/events.proto +++ b/proto/terra/feeburn/v1/events.proto @@ -8,8 +8,12 @@ option go_package = "github.com/terra-money/core/v2/x/feeburn/types"; // Event fired when fees are burned with the amount of fees burned message FeeBurnEvent { - // Amount of the payout - repeated cosmos.base.v1beta1.Coin fees_burn = 1 [ + // Amount of the payout + repeated cosmos.base.v1beta1.Coin fees_burn = 1 [(gogoproto.nullable) = false]; + + // Calculated % of the fees burned before truncating the decimal + string burn_rate = 2 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; } diff --git a/x/feeburn/post/post.go b/x/feeburn/post/post.go index b63fe446..55ccaa2e 100644 --- a/x/feeburn/post/post.go +++ b/x/feeburn/post/post.go @@ -1,6 +1,8 @@ package post import ( + "fmt" + errorsmod "cosmossdk.io/errors" "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" @@ -18,9 +20,9 @@ func NewFeeBurnDecorator(feeBurnKeeper FeeBurnKeeper, bankkeeper BankKeeper) Fee return FeeBurnDecorator{feeBurnKeeper, bankkeeper} } -func (bd FeeBurnDecorator) PostHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, success bool, next sdk.PostHandler) (newCtx sdk.Context, err error) { +func (fbd FeeBurnDecorator) PostHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, success bool, next sdk.PostHandler) (newCtx sdk.Context, err error) { // if the feeburn is not enabled then just continue with the next decorator - if !bd.feeBurnKeeper.GetParams(ctx).EnableFeeBurn { + if !fbd.feeBurnKeeper.GetParams(ctx).EnableFeeBurn { return next(ctx, tx, simulate, success) } @@ -48,23 +50,28 @@ func (bd FeeBurnDecorator) PostHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, return next(ctx, tx, simulate, success) } gasLimit := math.LegacyNewDecFromInt(sdk.NewInt(int64(gasMeter.Limit()))) - remainingGas := math.LegacyNewDecFromInt(sdk.NewInt(int64(gasMeter.GasRemaining()))) + remainingGas := math.LegacyNewDecFromInt(sdk.NewInt(int64(gasMeter.GasConsumed()))) + // Percentage of unused gas for this specific denom + burnRate := remainingGas.Quo(gasLimit) + fmt.Printf("remainingGas: %s\n", remainingGas) + fmt.Printf("gasLimit: %s\n", gasLimit) + fmt.Printf("burnRate: %s\n", burnRate) var toBurn sdk.Coins // Iterate over the transaction fees and calculate the proportional part // of the unused fees denominated in the tokens used to pay fo the fees // and add it to the toBurn variable that will be sent to the user. for _, txFee := range txFees { - // Percentage of unused gas for this specific denom - remainingGasProportion := remainingGas.Quo(gasLimit) // Given the percentage of unused gas, calculate the // proportional part of the fees that will be refunded // to the user in this specific denom. unusedFees := math.LegacyNewDecFromInt(txFee.Amount). - Mul(remainingGasProportion). + Mul(burnRate). TruncateInt() + fmt.Printf("math.LegacyNewDecFromInt(txFee.Amount) %s\n", math.LegacyNewDecFromInt(txFee.Amount)) + // When the unused fees are positive it means that the user // will receive a refund in this specific denom to its wallet. if unusedFees.IsPositive() { @@ -77,17 +84,23 @@ func (bd FeeBurnDecorator) PostHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, // Execute the refund to the user, if there is an error // return the error otherwise continue with the execution - err = bd.bankkeeper.BurnCoins(ctx, authtypes.FeeCollectorName, toBurn) + err = fbd.bankkeeper.BurnCoins(ctx, authtypes.FeeCollectorName, toBurn) if err != nil { return ctx, err } + // Emit an event to be able to track the fees burned + // because there can be a little bit of discrepancy + // between fees used and burned, because the proportional + // part of the fees is truncated to an integer. err = ctx.EventManager().EmitTypedEvent( - &types.FeeBurnEvent{FeesBurn: toBurn}, + &types.FeeBurnEvent{ + FeesBurn: toBurn, + BurnRate: burnRate, + }, ) if err != nil { return ctx, err } - return next(ctx, tx, simulate, success) } diff --git a/x/feeburn/post/post_test.go b/x/feeburn/post/post_test.go new file mode 100644 index 00000000..fc47fd8d --- /dev/null +++ b/x/feeburn/post/post_test.go @@ -0,0 +1,265 @@ +package post_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/suite" + "go.uber.org/mock/gomock" + + abci "github.com/cometbft/cometbft/abci/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + app "github.com/terra-money/core/v2/app/app_test" + "github.com/terra-money/core/v2/app/post/mocks" + post "github.com/terra-money/core/v2/x/feeburn/post" + "github.com/terra-money/core/v2/x/feeburn/types" +) + +type PostTestSuite struct { + app.AppTestSuite +} + +func TestAnteSuite(t *testing.T) { + suite.Run(t, new(PostTestSuite)) +} + +func (suite *PostTestSuite) TestCalculateFee() { + suite.Setup() + + // Create a mocked next post hanlder to assert the function being called. + ctrl := gomock.NewController(suite.T()) + mockedPostDecorator := mocks.NewMockPostDecorator(ctrl) + + feeBurnPost := post.NewFeeBurnDecorator( + suite.App.Keepers.FeeBurnKeeper, + suite.App.Keepers.BankKeeper, + ) + testCases := []struct { + name string + + // Input values + gasLimit uint64 + gasUsed uint64 + feeTx func() sdk.FeeTx + + // Expected values + expectedEvents sdk.Events + }{ + { + "Must burn half the transaction fee", + 100_000, + 48_991, // gas used is not exaclty 50k because it uses some gas to read from store and do some maths before burning . + func() sdk.FeeTx { + txBuilder := suite.EncodingConfig.TxConfig.NewTxBuilder() + txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin("uluna", sdk.NewInt(500)))) + return txBuilder.GetTx() + }, + sdk.Events( + sdk.Events{ + { + Type: "coin_spent", + Attributes: []abci.EventAttribute{ + { + Key: "spender", + Value: "terra17xpfvakm2amg962yls6f84z3kell8c5lkaeqfa", + Index: false, + }, + { + Key: "amount", + Value: "250uluna", + Index: false, + }, + }, + }, + { + Type: "burn", + Attributes: []abci.EventAttribute{ + { + Key: "burner", + Value: "terra17xpfvakm2amg962yls6f84z3kell8c5lkaeqfa", + Index: false, + }, + { + Key: "amount", + Value: "250uluna", + Index: false, + }, + }, + }, + { + Type: "terra.feeburn.v1.FeeBurnEvent", + Attributes: []abci.EventAttribute{ + { + Key: "fees_burn", + Value: "[{\"denom\":\"uluna\",\"amount\":\"250\"}]", + Index: false, + }, + }, + }, + }), + }, + { + "Must burn half the transaction fee containing two tokens", + 100_000, + 48_991, // gas used is not exaclty 50k because it uses some gas to read from store and do some maths before burning . + func() sdk.FeeTx { + txBuilder := suite.EncodingConfig.TxConfig.NewTxBuilder() + txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin("uluna", sdk.NewInt(500)), sdk.NewCoin("utoken", sdk.NewInt(250)))) + return txBuilder.GetTx() + }, + sdk.Events( + sdk.Events{ + { + Type: "coin_spent", + Attributes: []abci.EventAttribute{ + { + Key: "spender", + Value: "terra17xpfvakm2amg962yls6f84z3kell8c5lkaeqfa", + Index: false, + }, + { + Key: "amount", + Value: "250uluna,125utoken", + Index: false, + }, + }, + }, + { + Type: "burn", + Attributes: []abci.EventAttribute{ + { + Key: "burner", + Value: "terra17xpfvakm2amg962yls6f84z3kell8c5lkaeqfa", + Index: false, + }, + { + Key: "amount", + Value: "250uluna,125utoken", + Index: false, + }, + }, + }, + { + Type: "terra.feeburn.v1.FeeBurnEvent", + Attributes: []abci.EventAttribute{ + { + Key: "fees_burn", + Value: "[{\"denom\":\"uluna\",\"amount\":\"250\"},{\"denom\":\"utoken\",\"amount\":\"125\"}]", + Index: false, + }, + }, + }, + }), + }, + { + "Must burn a quarter of the transaction fee containing two tokens rounding down to the nearest integer", + 100_000, + 23_991, // gas used is not exaclty 25k because it uses some gas to read from store and do some maths before burning . + func() sdk.FeeTx { + txBuilder := suite.EncodingConfig.TxConfig.NewTxBuilder() + txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin("uluna", sdk.NewInt(250)), sdk.NewCoin("utoken", sdk.NewInt(125)))) + return txBuilder.GetTx() + }, + sdk.Events( + sdk.Events{ + { + Type: "coin_spent", + Attributes: []abci.EventAttribute{ + { + Key: "spender", + Value: "terra17xpfvakm2amg962yls6f84z3kell8c5lkaeqfa", + Index: false, + }, + { + Key: "amount", + Value: "187uluna,93utoken", + Index: false, + }, + }, + }, + { + Type: "burn", + Attributes: []abci.EventAttribute{ + { + Key: "burner", + Value: "terra17xpfvakm2amg962yls6f84z3kell8c5lkaeqfa", + Index: false, + }, + { + Key: "amount", + Value: "187uluna,93utoken", + Index: false, + }, + }, + }, + { + Type: "terra.feeburn.v1.FeeBurnEvent", + Attributes: []abci.EventAttribute{ + { + Key: "fees_burn", + Value: "[{\"denom\":\"uluna\",\"amount\":\"187\"},{\"denom\":\"utoken\",\"amount\":\"93\"}]", + Index: false, + }, + }, + }, + }), + }, + { + "Must define zero fees to skip the burning process", + 5_000, + 0, + func() sdk.FeeTx { + txBuilder := suite.EncodingConfig.TxConfig.NewTxBuilder() + txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin("uluna", sdk.NewInt(0)))) + return txBuilder.GetTx() + }, + sdk.EmptyEvents(), + }, + { + "Must disable the module to skip the burning process", + 5_000, + 0, + func() sdk.FeeTx { + suite.App.Keepers.FeeBurnKeeper.SetParams(suite.Ctx, types.Params{EnableFeeBurn: false}) + return suite.EncodingConfig.TxConfig.NewTxBuilder().GetTx() + }, + sdk.EmptyEvents(), + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.name), func() { + // Setup the test case, removing the events from the previous + // gas meters set the gas limit and gas used. + feeTx := tc.feeTx() + suite.Ctx = suite.Ctx.WithEventManager(sdk.NewEventManager()) + suite.Ctx = suite.Ctx.WithGasMeter(sdk.NewGasMeter(tc.gasLimit)) + suite.Ctx.GasMeter().ConsumeGas(tc.gasUsed, "test") + + // assert the next hanlder is called once + mockedPostDecorator. + EXPECT(). + PostHandle(gomock.Any(), gomock.Any(), false, true, gomock.Any()). + Times(1) + + _, err := feeBurnPost.PostHandle(suite.Ctx, + feeTx, + false, + true, + func(ctx sdk.Context, tx sdk.Tx, simulate bool, success bool) (sdk.Context, error) { + // Overwrite the context with the context returned from the handler. + suite.Ctx = ctx + return mockedPostDecorator.PostHandle(ctx, tx, simulate, success, nil) + }, + ) + + suite.Require().NoError(err) + suite.Require().NotNil(suite.Ctx) + suite.Require().Equal( + tc.expectedEvents, + suite.Ctx.EventManager().Events(), + ) + }) + } +} diff --git a/x/feeburn/types/events.pb.go b/x/feeburn/types/events.pb.go index 16e52fc2..0f532b0d 100644 --- a/x/feeburn/types/events.pb.go +++ b/x/feeburn/types/events.pb.go @@ -5,6 +5,7 @@ package types import ( fmt "fmt" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" types "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" @@ -28,6 +29,8 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type FeeBurnEvent struct { // Amount of the payout FeesBurn []types.Coin `protobuf:"bytes,1,rep,name=fees_burn,json=feesBurn,proto3" json:"fees_burn"` + // Calculated % of the fees burned before truncating the decimal + BurnRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=burn_rate,json=burnRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"burn_rate"` } func (m *FeeBurnEvent) Reset() { *m = FeeBurnEvent{} } @@ -77,22 +80,25 @@ func init() { func init() { proto.RegisterFile("terra/feeburn/v1/events.proto", fileDescriptor_f6c4b84def882b33) } var fileDescriptor_f6c4b84def882b33 = []byte{ - // 235 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x3c, 0xcf, 0x31, 0x4b, 0xc4, 0x30, - 0x14, 0x07, 0xf0, 0x16, 0x45, 0xb4, 0x3a, 0xc8, 0xe1, 0xa0, 0x07, 0x46, 0x71, 0x72, 0xf1, 0x3d, - 0x72, 0xae, 0x4e, 0x15, 0xc5, 0xc1, 0xc9, 0xd1, 0x45, 0x9a, 0xf0, 0xae, 0x76, 0x68, 0xde, 0x91, - 0xa4, 0xc1, 0xfb, 0x16, 0x7e, 0xac, 0x1b, 0x6f, 0x74, 0x12, 0x69, 0xbf, 0x88, 0x24, 0x2d, 0xb7, - 0x3d, 0xf2, 0xe7, 0xff, 0xe3, 0x9f, 0xe2, 0xd2, 0x93, 0xb5, 0x15, 0x2e, 0x89, 0x54, 0x67, 0x0d, - 0x06, 0x89, 0x14, 0xc8, 0x78, 0x07, 0x2b, 0xcb, 0x9e, 0x67, 0xa7, 0x29, 0x86, 0x29, 0x86, 0x20, - 0xe7, 0x42, 0xb3, 0x6b, 0xd9, 0xa1, 0xaa, 0x1c, 0x61, 0x90, 0x8a, 0x7c, 0x25, 0x51, 0x73, 0x63, - 0xc6, 0xc6, 0xfc, 0xac, 0xe6, 0x9a, 0xd3, 0x89, 0xf1, 0x1a, 0x5f, 0x6f, 0x5e, 0x8b, 0x93, 0x67, - 0xa2, 0xb2, 0xb3, 0xe6, 0x29, 0xf2, 0xb3, 0x87, 0xe2, 0x68, 0x49, 0xe4, 0x3e, 0xa2, 0x7a, 0x9e, - 0x5f, 0xef, 0xdd, 0x1e, 0x2f, 0x2e, 0x60, 0x94, 0x21, 0xca, 0x30, 0xc9, 0xf0, 0xc8, 0x8d, 0x29, - 0xf7, 0x37, 0xbf, 0x57, 0xd9, 0xdb, 0x61, 0x6c, 0x44, 0xa2, 0x7c, 0xd9, 0xf4, 0x22, 0xdf, 0xf6, - 0x22, 0xff, 0xeb, 0x45, 0xfe, 0x3d, 0x88, 0x6c, 0x3b, 0x88, 0xec, 0x67, 0x10, 0xd9, 0x3b, 0xd4, - 0x8d, 0xff, 0xec, 0x14, 0x68, 0x6e, 0x31, 0x4d, 0xbf, 0x6b, 0xd9, 0xd0, 0x1a, 0x35, 0x5b, 0xc2, - 0xb0, 0xc0, 0xaf, 0xdd, 0x4f, 0xfd, 0x7a, 0x45, 0x4e, 0x1d, 0xa4, 0x79, 0xf7, 0xff, 0x01, 0x00, - 0x00, 0xff, 0xff, 0xbb, 0x3e, 0xfd, 0xb8, 0x07, 0x01, 0x00, 0x00, + // 282 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0xd0, 0xbd, 0x4e, 0xc3, 0x30, + 0x10, 0x07, 0xf0, 0x18, 0x10, 0x6a, 0x02, 0x03, 0x8a, 0x18, 0x4a, 0x25, 0xdc, 0x8a, 0x01, 0x75, + 0xa9, 0x4f, 0x29, 0x2b, 0x53, 0xf8, 0x10, 0x12, 0x5b, 0x46, 0x96, 0x2a, 0x09, 0xd7, 0x10, 0xa1, + 0xf8, 0x2a, 0xdb, 0x89, 0xe8, 0x5b, 0xb0, 0xf2, 0x46, 0x1d, 0x3b, 0x22, 0x86, 0x0a, 0x25, 0x2f, + 0x82, 0x9c, 0x44, 0xa8, 0x93, 0x4f, 0x3e, 0xff, 0x7f, 0xf2, 0x9d, 0x77, 0x69, 0x50, 0xa9, 0x18, + 0x96, 0x88, 0x49, 0xa9, 0x24, 0x54, 0x01, 0x60, 0x85, 0xd2, 0x68, 0xb1, 0x52, 0x64, 0xc8, 0x3f, + 0x6b, 0xdb, 0xa2, 0x6f, 0x8b, 0x2a, 0x18, 0xf1, 0x94, 0x74, 0x41, 0x1a, 0x92, 0x58, 0x23, 0x54, + 0x41, 0x82, 0x26, 0x0e, 0x20, 0xa5, 0x5c, 0x76, 0x89, 0xd1, 0x79, 0x46, 0x19, 0xb5, 0x25, 0xd8, + 0xaa, 0xbb, 0xbd, 0xfa, 0x62, 0xde, 0xe9, 0x23, 0x62, 0x58, 0x2a, 0xf9, 0x60, 0x7d, 0xff, 0xd6, + 0x73, 0x97, 0x88, 0x7a, 0x61, 0xd9, 0x21, 0x9b, 0x1c, 0x4e, 0x4f, 0xe6, 0x17, 0xa2, 0xa3, 0x85, + 0xa5, 0x45, 0x4f, 0x8b, 0x3b, 0xca, 0x65, 0x78, 0xb4, 0xd9, 0x8d, 0x9d, 0x68, 0x60, 0x13, 0x96, + 0xf0, 0x9f, 0x3d, 0xd7, 0x06, 0x17, 0x2a, 0x36, 0x38, 0x3c, 0x98, 0xb0, 0xa9, 0x1b, 0x0a, 0xfb, + 0xe4, 0x67, 0x37, 0xbe, 0xce, 0x72, 0xf3, 0x56, 0x26, 0x22, 0xa5, 0x02, 0xfa, 0xaf, 0x76, 0xc7, + 0x4c, 0xbf, 0xbe, 0x83, 0x59, 0xaf, 0x50, 0x8b, 0x7b, 0x4c, 0xa3, 0x81, 0x05, 0xa2, 0xd8, 0x60, + 0xf8, 0xb4, 0xa9, 0x39, 0xdb, 0xd6, 0x9c, 0xfd, 0xd6, 0x9c, 0x7d, 0x36, 0xdc, 0xd9, 0x36, 0xdc, + 0xf9, 0x6e, 0xb8, 0xf3, 0x22, 0xf6, 0xac, 0x76, 0x11, 0xb3, 0x82, 0x24, 0xae, 0x21, 0x25, 0x85, + 0x50, 0xcd, 0xe1, 0xe3, 0x7f, 0x6f, 0xad, 0x9b, 0x1c, 0xb7, 0xc3, 0xde, 0xfc, 0x05, 0x00, 0x00, + 0xff, 0xff, 0xcd, 0x20, 0x9b, 0xc7, 0x55, 0x01, 0x00, 0x00, } func (m *FeeBurnEvent) Marshal() (dAtA []byte, err error) { @@ -115,6 +121,16 @@ func (m *FeeBurnEvent) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size := m.BurnRate.Size() + i -= size + if _, err := m.BurnRate.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 if len(m.FeesBurn) > 0 { for iNdEx := len(m.FeesBurn) - 1; iNdEx >= 0; iNdEx-- { { @@ -155,6 +171,8 @@ func (m *FeeBurnEvent) Size() (n int) { n += 1 + l + sovEvents(uint64(l)) } } + l = m.BurnRate.Size() + n += 1 + l + sovEvents(uint64(l)) return n } @@ -227,6 +245,40 @@ func (m *FeeBurnEvent) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BurnRate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.BurnRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipEvents(dAtA[iNdEx:])