From fcc8fca76d293ed63f662a0651dca64bbeb4c2ec Mon Sep 17 00:00:00 2001 From: morde08 Date: Wed, 24 Jul 2024 09:35:56 -0700 Subject: [PATCH 1/2] add additional tags for identification on nightly performance test runs (#2539) --- .github/actions/performance-tests/art.yaml | 2 ++ .github/workflows/ci-nightly-performance-testing.yaml | 3 +++ 2 files changed, 5 insertions(+) diff --git a/.github/actions/performance-tests/art.yaml b/.github/actions/performance-tests/art.yaml index b6c5b688fc..806a4d6321 100644 --- a/.github/actions/performance-tests/art.yaml +++ b/.github/actions/performance-tests/art.yaml @@ -19,6 +19,8 @@ config: pushgateway: 'https://pushgateway-testnet.rpc.zetachain.com/-=CLOUDFLARE_UUID=-' tags: - 'type:loadtest' + - 'testId:-=GITHUB_ACTION=-' + - 'jobName:evm-performance-test' summary: true reports: - type: "html" diff --git a/.github/workflows/ci-nightly-performance-testing.yaml b/.github/workflows/ci-nightly-performance-testing.yaml index a506fd88b1..d4676b5271 100644 --- a/.github/workflows/ci-nightly-performance-testing.yaml +++ b/.github/workflows/ci-nightly-performance-testing.yaml @@ -38,11 +38,14 @@ jobs: env: CLOUDFLARE_UUID: ${{ secrets.CLOUDFLARE_UUID }} ENDPOINT: ${{ inputs.endpoint || 'http://localhost:9545' }} + GITHUB_ACTION: ${{ github.action }} run: | # Replace -=endpoint_to_test=- placeholder in the art.yaml file with the endpoint_to_test value sed -i "s|-=endpoint_to_test=-|${ENDPOINT}|g" .github/actions/performance-tests/art.yaml # Replace -=CLOUDFLARE_UUID=- placeholder in the art.yaml file with the correct value sed -i "s|-=CLOUDFLARE_UUID=-|${CLOUDFLARE_UUID}|g" .github/actions/performance-tests/art.yaml + # Replace -=GITHUB_ACTION=- placeholder in the art.yaml file with the correct value + sed -i "s|-=GITHUB_ACTION=-|${GITHUB_ACTION}|g" .github/actions/performance-tests/art.yaml cat .github/actions/performance-tests/art.yaml - name: "EXECUTE:PERFORMANCE:TESTS" From a27aa9a62d97e1f04e2b636fdb510198ed109254 Mon Sep 17 00:00:00 2001 From: Dmitry S <11892559+swift1337@users.noreply.github.com> Date: Wed, 24 Jul 2024 19:35:55 +0200 Subject: [PATCH 2/2] feat(crosschain): store priorityFee (GasTipCap) for EVM chains (#2483) * Add priorityFee & remove supply for msg VoteGasPrice * Vote priorityFee to zetacore * Refactor vote gas price msg * Add priority fees to cross-chain keeper * Fix conflicts * Add priorityFee to cctx outbound data * Update changelog * `make generate` * Move SliceMedianValue to math * Rename GetMedianGasPriceInUint to GetMedianGasValues * Reserve proto range for cctx * Minor PR comments * Bump priorityFee for TSS migration * Implement priorityFee with priorityFee check based on block header * Fix * Fix tests * Add `IncreaseUintByPercent` * Bump priorityFee when needed * Fix typo --- changelog.md | 1 + .../zetacored_tx_crosschain_vote-gas-price.md | 2 +- docs/openapi/openapi.swagger.yaml | 9 + docs/spec/crosschain/messages.md | 2 +- pkg/math/cosmos_uint.go | 21 ++ pkg/math/cosmos_uint_test.go | 42 +++ pkg/math/slice.go | 53 ++++ pkg/math/slice_test.go | 75 ++++++ .../zetacore/crosschain/cross_chain_tx.proto | 8 +- .../zetacore/crosschain/gas_price.proto | 6 + proto/zetachain/zetacore/crosschain/tx.proto | 7 +- testutil/network/genesis_state.go | 13 +- .../crosschain/cross_chain_tx_pb.d.ts | 5 + .../zetacore/crosschain/gas_price_pb.d.ts | 9 + .../zetachain/zetacore/crosschain/tx_pb.d.ts | 8 +- x/crosschain/client/cli/cli_gas_price.go | 21 +- x/crosschain/keeper/abci.go | 15 +- x/crosschain/keeper/abci_test.go | 12 +- x/crosschain/keeper/cctx_gateway_observers.go | 3 +- x/crosschain/keeper/gas_payment.go | 111 +++++--- x/crosschain/keeper/gas_price.go | 31 ++- .../keeper/grpc_query_zeta_conversion_rate.go | 2 +- x/crosschain/keeper/initiate_outbound.go | 14 +- .../keeper/msg_server_migrate_tss_funds.go | 5 +- .../msg_server_migrate_tss_funds_test.go | 21 +- .../keeper/msg_server_vote_gas_price.go | 98 ++++--- .../keeper/msg_server_vote_gas_price_test.go | 119 ++++++--- .../keeper/msg_server_whitelist_erc20.go | 19 +- x/crosschain/types/cctx.go | 1 + x/crosschain/types/cross_chain_tx.pb.go | 191 +++++++++----- x/crosschain/types/errors.go | 1 + x/crosschain/types/gas_price.pb.go | 188 +++++++++++--- x/crosschain/types/keys.go | 3 +- x/crosschain/types/message_vote_gas_price.go | 8 +- .../types/message_vote_gas_price_test.go | 6 +- x/crosschain/types/outbound_params.go | 16 ++ x/crosschain/types/tx.pb.go | 245 ++++++++---------- .../chains/bitcoin/observer/observer.go | 5 +- zetaclient/chains/evm/observer/observer.go | 79 +----- .../chains/evm/observer/observer_gas.go | 147 +++++++++++ .../chains/evm/observer/observer_gas_test.go | 115 ++++++++ zetaclient/chains/interfaces/interfaces.go | 4 +- zetaclient/testutils/mocks/evm_rpc.go | 22 ++ zetaclient/testutils/mocks/zetacore_client.go | 18 +- zetaclient/zetacore/client_vote.go | 6 +- zetaclient/zetacore/tx_test.go | 2 +- 46 files changed, 1289 insertions(+), 500 deletions(-) create mode 100644 pkg/math/cosmos_uint.go create mode 100644 pkg/math/cosmos_uint_test.go create mode 100644 pkg/math/slice.go create mode 100644 pkg/math/slice_test.go create mode 100644 zetaclient/chains/evm/observer/observer_gas.go create mode 100644 zetaclient/chains/evm/observer/observer_gas_test.go diff --git a/changelog.md b/changelog.md index f8857f3e9e..29ef9db9b6 100644 --- a/changelog.md +++ b/changelog.md @@ -34,6 +34,7 @@ * [2465](https://github.com/zeta-chain/node/pull/2465) - add Solana inbound SOL token observation * [2497](https://github.com/zeta-chain/node/pull/2416) - support for runtime chain (de)provisioning * [2518](https://github.com/zeta-chain/node/pull/2518) - add support for Solana address in zetacore +* [2483](https://github.com/zeta-chain/node/pull/2483) - add priorityFee (gasTipCap) gas to the state ### Refactor diff --git a/docs/cli/zetacored/zetacored_tx_crosschain_vote-gas-price.md b/docs/cli/zetacored/zetacored_tx_crosschain_vote-gas-price.md index e8efad044a..17b8758f85 100644 --- a/docs/cli/zetacored/zetacored_tx_crosschain_vote-gas-price.md +++ b/docs/cli/zetacored/zetacored_tx_crosschain_vote-gas-price.md @@ -3,7 +3,7 @@ Broadcast message to vote gas price ``` -zetacored tx crosschain vote-gas-price [chain] [price] [supply] [blockNumber] [flags] +zetacored tx crosschain vote-gas-price [chain] [price] [priorityFee] [blockNumber] [flags] ``` ### Options diff --git a/docs/openapi/openapi.swagger.yaml b/docs/openapi/openapi.swagger.yaml index 53361f96a2..f1cf579ebe 100644 --- a/docs/openapi/openapi.swagger.yaml +++ b/docs/openapi/openapi.swagger.yaml @@ -57141,6 +57141,13 @@ definitions: median_index: type: string format: uint64 + title: index of the median gas price in the prices array + priority_fees: + type: array + items: + type: string + format: uint64 + title: priority fees for EIP-1559 crosschainInboundHashToCctx: type: object properties: @@ -57260,6 +57267,8 @@ definitions: format: uint64 gas_price: type: string + gas_priority_fee: + type: string hash: type: string title: |- diff --git a/docs/spec/crosschain/messages.md b/docs/spec/crosschain/messages.md index 3ac1d484bb..feb02afc1f 100644 --- a/docs/spec/crosschain/messages.md +++ b/docs/spec/crosschain/messages.md @@ -61,8 +61,8 @@ message MsgVoteGasPrice { string creator = 1; int64 chain_id = 2; uint64 price = 3; + uint64 priority_fee = 6; uint64 block_number = 4; - string supply = 5; } ``` diff --git a/pkg/math/cosmos_uint.go b/pkg/math/cosmos_uint.go new file mode 100644 index 0000000000..283944ed87 --- /dev/null +++ b/pkg/math/cosmos_uint.go @@ -0,0 +1,21 @@ +package math + +import "cosmossdk.io/math" + +// IncreaseUintByPercent is a function that increases Uint by a percentage. +// Example: IncreaseUintByPercent(4000, 20) = 4000 * 1,2 = 4800 +// Returns result and increase amount. +func IncreaseUintByPercent(amount math.Uint, percent uint64) (math.Uint, math.Uint) { + switch { + case percent == 0: + // noop + return amount, math.ZeroUint() + case percent%100 == 0: + // optimization: a simple multiplication + increase := amount.MulUint64(percent / 100) + return amount.Add(increase), increase + default: + increase := amount.MulUint64(percent).QuoUint64(100) + return amount.Add(increase), increase + } +} diff --git a/pkg/math/cosmos_uint_test.go b/pkg/math/cosmos_uint_test.go new file mode 100644 index 0000000000..e98debb775 --- /dev/null +++ b/pkg/math/cosmos_uint_test.go @@ -0,0 +1,42 @@ +package math + +import ( + "fmt" + "testing" + + "cosmossdk.io/math" + "github.com/stretchr/testify/assert" +) + +func TestIncreaseUintByPercent(t *testing.T) { + for i, tt := range []struct { + in math.Uint + percent uint64 + expected math.Uint + }{ + {in: math.NewUint(444), percent: 0, expected: math.NewUint(444)}, + {in: math.NewUint(100), percent: 4, expected: math.NewUint(104)}, + {in: math.NewUint(100), percent: 100, expected: math.NewUint(200)}, + {in: math.NewUint(4000), percent: 50, expected: math.NewUint(6000)}, + {in: math.NewUint(2500), percent: 100, expected: math.NewUint(5000)}, + {in: math.NewUint(10000), percent: 33, expected: math.NewUint(13300)}, + } { + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + actual, increase := IncreaseUintByPercent(tt.in, tt.percent) + + original := actual.Sub(increase).Uint64() + + assert.Equal(t, int(tt.expected.Uint64()), int(actual.Uint64())) + assert.Equal(t, int(tt.in.Uint64()), int(original)) + + t.Logf( + "input: %d, percent: %d, expected: %d, actual: %d, increase: %d", + tt.in.Uint64(), + tt.percent, + tt.expected.Uint64(), + actual.Uint64(), + increase.Uint64(), + ) + }) + } +} diff --git a/pkg/math/slice.go b/pkg/math/slice.go new file mode 100644 index 0000000000..2b2b78761b --- /dev/null +++ b/pkg/math/slice.go @@ -0,0 +1,53 @@ +package math + +import "slices" + +type number interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 +} + +// SliceMedianValue returns the median value of the given slice. +// Returns 0 for an empty slice. If inPlace is true, the input slice will be sorted in place. +// Otherwise, a copy of the input slice will be sorted. +func SliceMedianValue[T number](items []T, inPlace bool) T { + if inPlace { + return sliceMedianValue(items) + } + + copied := make([]T, len(items)) + copy(copied, items) + + out := sliceMedianValue(copied) + + // We don't need the copy anymore + //nolint:ineffassign // let's help the garbage collector :) + copied = nil + + return out +} + +func sliceMedianValue[T number](items []T) T { + switch len(items) { + case 0: + return 0 + case 1: + return items[0] + } + + slices.Sort(items) + + // note that int division is used here e.g. 5/2 => 2 + + // []int{1 2 3 4 5} => items[(5/2)] => items[2] => 3 + if len(items)%2 == 1 { + return items[len(items)/2] + } + + // odd number of items + rightIndex := len(items) / 2 + leftIndex := rightIndex - 1 + + // []int{1 2 3 4} => (items[1] + items[2]) / 2 => 5/2 => 2 + return (items[leftIndex] + items[rightIndex]) / 2 +} diff --git a/pkg/math/slice_test.go b/pkg/math/slice_test.go new file mode 100644 index 0000000000..558842dd98 --- /dev/null +++ b/pkg/math/slice_test.go @@ -0,0 +1,75 @@ +package math + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSliceMedianValue(t *testing.T) { + for _, tt := range []struct { + name string + input []int + expected int + inPlace bool + }{ + { + name: "empty", + input: nil, + expected: 0, + inPlace: false, + }, + { + name: "single", + input: []int{10}, + expected: 10, + }, + { + name: "two", + input: []int{10, 20}, + expected: 15, + }, + { + name: "even", + input: []int{30, 20, 10, 20}, + expected: 20, + }, + { + name: "even in-place", + input: []int{30, 20, 10, 20}, + expected: 20, + inPlace: true, + }, + { + name: "odd", + input: []int{5, 5, 6, 1, 1, 1, 4}, + expected: 4, + }, + { + name: "odd in-place", + input: []int{1, 1, 1, 1, 7, 7, 7, 7}, + expected: 4, + }, + } { + t.Run(tt.name, func(t *testing.T) { + // ASSERT + // Given a copy of the input slice + var snapshot []int + for _, v := range tt.input { + snapshot = append(snapshot, v) + } + + // ACT + out := SliceMedianValue(tt.input, tt.inPlace) + + // ASSERT + assert.Equal(t, tt.expected, out) + + // Check that elements of the input slice are unchanged + if !tt.inPlace { + assert.Equal(t, snapshot, tt.input) + } + }) + } + +} diff --git a/proto/zetachain/zetacore/crosschain/cross_chain_tx.proto b/proto/zetachain/zetacore/crosschain/cross_chain_tx.proto index 1e88231751..88ca547482 100644 --- a/proto/zetachain/zetacore/crosschain/cross_chain_tx.proto +++ b/proto/zetachain/zetacore/crosschain/cross_chain_tx.proto @@ -17,7 +17,7 @@ enum CctxStatus { Reverted = 5; // inbound reverted. Aborted = 6; // inbound tx error or invalid paramters and cannot revert; just abort. - // But the amount can be refunded to zetachain using and admin proposal + // But the amount can be refunded to zetachain using and admin proposal } enum TxFinalizationStatus { @@ -28,7 +28,7 @@ enum TxFinalizationStatus { } message InboundParams { string sender = 1; // this address is the immediate contract/EOA that calls - // the Connector.send() + // the Connector.send() int64 sender_chain_id = 2; string tx_origin = 3; // this address is the EOA that signs the inbound tx pkg.coin.CoinType coin_type = 4; @@ -65,6 +65,7 @@ message OutboundParams { uint64 tss_nonce = 5; uint64 gas_limit = 6; string gas_price = 7; + string gas_priority_fee = 23; // the above are commands for zetaclients // the following fields are used when the outbound tx is mined string hash = 8; @@ -78,6 +79,9 @@ message OutboundParams { uint64 effective_gas_limit = 22; string tss_pubkey = 11; TxFinalizationStatus tx_finalization_status = 12; + + // not used. do not edit. + reserved 13 to 19; } message Status { diff --git a/proto/zetachain/zetacore/crosschain/gas_price.proto b/proto/zetachain/zetacore/crosschain/gas_price.proto index d325f3c2ac..c6f0b7719d 100644 --- a/proto/zetachain/zetacore/crosschain/gas_price.proto +++ b/proto/zetachain/zetacore/crosschain/gas_price.proto @@ -9,6 +9,12 @@ message GasPrice { int64 chain_id = 3; repeated string signers = 4; repeated uint64 block_nums = 5; + repeated uint64 prices = 6; + + // index of the median gas price in the prices array uint64 median_index = 7; + + // priority fees for EIP-1559 + repeated uint64 priority_fees = 8; } diff --git a/proto/zetachain/zetacore/crosschain/tx.proto b/proto/zetachain/zetacore/crosschain/tx.proto index 5392ee6061..2bff84f733 100644 --- a/proto/zetachain/zetacore/crosschain/tx.proto +++ b/proto/zetachain/zetacore/crosschain/tx.proto @@ -104,10 +104,15 @@ message MsgRemoveOutboundTrackerResponse {} message MsgVoteGasPrice { string creator = 1; + int64 chain_id = 2; + uint64 price = 3; + uint64 priority_fee = 6; + uint64 block_number = 4; - string supply = 5; + + reserved 5; // deprecated `string supply` } message MsgVoteGasPriceResponse {} diff --git a/testutil/network/genesis_state.go b/testutil/network/genesis_state.go index 6a4bcec672..e391526328 100644 --- a/testutil/network/genesis_state.go +++ b/testutil/network/genesis_state.go @@ -220,12 +220,13 @@ func AddCrosschainData( state.GasPriceList = append( state.GasPriceList, &types.GasPrice{ - Creator: "ANY", - ChainId: int64(i), - Index: strconv.Itoa(i), - Prices: []uint64{}, - BlockNums: []uint64{}, - Signers: []string{}, + Creator: "ANY", + ChainId: int64(i), + Index: strconv.Itoa(i), + Prices: []uint64{}, + PriorityFees: []uint64{}, + BlockNums: []uint64{}, + Signers: []string{}, }, ) } diff --git a/typescript/zetachain/zetacore/crosschain/cross_chain_tx_pb.d.ts b/typescript/zetachain/zetacore/crosschain/cross_chain_tx_pb.d.ts index 7c25cd1be0..c4839a61f5 100644 --- a/typescript/zetachain/zetacore/crosschain/cross_chain_tx_pb.d.ts +++ b/typescript/zetachain/zetacore/crosschain/cross_chain_tx_pb.d.ts @@ -228,6 +228,11 @@ export declare class OutboundParams extends Message { */ gasPrice: string; + /** + * @generated from field: string gas_priority_fee = 23; + */ + gasPriorityFee: string; + /** * the above are commands for zetaclients * the following fields are used when the outbound tx is mined diff --git a/typescript/zetachain/zetacore/crosschain/gas_price_pb.d.ts b/typescript/zetachain/zetacore/crosschain/gas_price_pb.d.ts index 7790bbde92..8bb2debc02 100644 --- a/typescript/zetachain/zetacore/crosschain/gas_price_pb.d.ts +++ b/typescript/zetachain/zetacore/crosschain/gas_price_pb.d.ts @@ -41,10 +41,19 @@ export declare class GasPrice extends Message { prices: bigint[]; /** + * index of the median gas price in the prices array + * * @generated from field: uint64 median_index = 7; */ medianIndex: bigint; + /** + * priority fees for EIP-1559 + * + * @generated from field: repeated uint64 priority_fees = 8; + */ + priorityFees: bigint[]; + constructor(data?: PartialMessage); static readonly runtime: typeof proto3; diff --git a/typescript/zetachain/zetacore/crosschain/tx_pb.d.ts b/typescript/zetachain/zetacore/crosschain/tx_pb.d.ts index 9a854f9896..e15cf71780 100644 --- a/typescript/zetachain/zetacore/crosschain/tx_pb.d.ts +++ b/typescript/zetachain/zetacore/crosschain/tx_pb.d.ts @@ -420,14 +420,14 @@ export declare class MsgVoteGasPrice extends Message { price: bigint; /** - * @generated from field: uint64 block_number = 4; + * @generated from field: uint64 priority_fee = 6; */ - blockNumber: bigint; + priorityFee: bigint; /** - * @generated from field: string supply = 5; + * @generated from field: uint64 block_number = 4; */ - supply: string; + blockNumber: bigint; constructor(data?: PartialMessage); diff --git a/x/crosschain/client/cli/cli_gas_price.go b/x/crosschain/client/cli/cli_gas_price.go index a588dced87..a08d16eed1 100644 --- a/x/crosschain/client/cli/cli_gas_price.go +++ b/x/crosschain/client/cli/cli_gas_price.go @@ -4,6 +4,7 @@ import ( "context" "strconv" + "cosmossdk.io/errors" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" @@ -77,34 +78,40 @@ func CmdShowGasPrice() *cobra.Command { func CmdVoteGasPrice() *cobra.Command { cmd := &cobra.Command{ - Use: "vote-gas-price [chain] [price] [supply] [blockNumber]", + Use: "vote-gas-price [chain] [price] [priorityFee] [blockNumber]", Short: "Broadcast message to vote gas price", Args: cobra.ExactArgs(4), RunE: func(cmd *cobra.Command, args []string) error { argsChain, err := strconv.ParseInt(args[0], 10, 64) if err != nil { - return err + return errors.Wrapf(err, "invalid chain id %q", args[0]) } + argsPrice, err := strconv.ParseUint(args[1], 10, 64) if err != nil { - return err + return errors.Wrapf(err, "invalid price %q", args[1]) + } + + argsPriorityFee, err := strconv.ParseUint(args[2], 10, 64) + if err != nil { + return errors.Wrapf(err, "invalid priorityFee %q", args[2]) } - argsSupply := args[2] argsBlockNumber, err := strconv.ParseUint(args[3], 10, 64) if err != nil { - return err + return errors.Wrapf(err, "invalid blockNumber %q", args[3]) } + clientCtx, err := client.GetClientTxContext(cmd) if err != nil { - return err + return errors.Wrap(err, "failed to get client context") } msg := types.NewMsgVoteGasPrice( clientCtx.GetFromAddress().String(), argsChain, argsPrice, - argsSupply, + argsPriorityFee, argsBlockNumber, ) diff --git a/x/crosschain/keeper/abci.go b/x/crosschain/keeper/abci.go index ee6cfb3aa3..494603f473 100644 --- a/x/crosschain/keeper/abci.go +++ b/x/crosschain/keeper/abci.go @@ -9,6 +9,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" zetachains "github.com/zeta-chain/zetacore/pkg/chains" + mathpkg "github.com/zeta-chain/zetacore/pkg/math" "github.com/zeta-chain/zetacore/x/crosschain/types" observertypes "github.com/zeta-chain/zetacore/x/observer/types" ) @@ -120,7 +121,7 @@ func CheckAndUpdateCctxGasPrice( // compute gas price increase chainID := cctx.GetCurrentOutboundParam().ReceiverChainId - medianGasPrice, isFound := k.GetMedianGasPriceInUint(ctx, chainID) + medianGasPrice, medianPriorityFee, isFound := k.GetMedianGasValues(ctx, chainID) if !isFound { return math.ZeroUint(), math.ZeroUint(), cosmoserrors.Wrap( types.ErrUnableToGetGasPrice, @@ -146,6 +147,17 @@ func CheckAndUpdateCctxGasPrice( return math.ZeroUint(), math.ZeroUint(), nil } + newPriorityFee, _ := mathpkg.IncreaseUintByPercent(medianPriorityFee, uint64(flags.GasPriceIncreasePercent)) + + // should not happen + if newPriorityFee.GT(newGasPrice) { + return math.ZeroUint(), math.ZeroUint(), fmt.Errorf( + "priorityFee %s is greater than new gasPrice %s", + newPriorityFee.String(), + newGasPrice.String(), + ) + } + // withdraw additional fees from the gas stability pool gasLimit := math.NewUint(cctx.GetCurrentOutboundParam().GasLimit) additionalFees := gasLimit.Mul(gasPriceIncrease) @@ -158,6 +170,7 @@ func CheckAndUpdateCctxGasPrice( // set new gas price and last update timestamp cctx.GetCurrentOutboundParam().GasPrice = newGasPrice.String() + cctx.GetCurrentOutboundParam().GasPriorityFee = newPriorityFee.String() cctx.CctxStatus.LastUpdateTimestamp = ctx.BlockHeader().Time.Unix() k.SetCrossChainTx(ctx, cctx) diff --git a/x/crosschain/keeper/abci_test.go b/x/crosschain/keeper/abci_test.go index 817f930079..7ac38cd917 100644 --- a/x/crosschain/keeper/abci_test.go +++ b/x/crosschain/keeper/abci_test.go @@ -116,6 +116,7 @@ func TestCheckAndUpdateCctxGasPrice(t *testing.T) { flags observertypes.GasPriceIncreaseFlags blockTimestamp time.Time medianGasPrice uint64 + medianPriorityFee uint64 withdrawFromGasStabilityPoolReturn error expectWithdrawFromGasStabilityPoolCall bool expectedGasPriceIncrease math.Uint @@ -140,6 +141,7 @@ func TestCheckAndUpdateCctxGasPrice(t *testing.T) { flags: observertypes.DefaultGasPriceIncreaseFlags, blockTimestamp: retryIntervalReached, medianGasPrice: 50, + medianPriorityFee: 20, withdrawFromGasStabilityPoolReturn: nil, expectWithdrawFromGasStabilityPoolCall: true, expectedGasPriceIncrease: math.NewUint(50), // 100% medianGasPrice @@ -354,15 +356,17 @@ func TestCheckAndUpdateCctxGasPrice(t *testing.T) { // set median gas price if not zero if tc.medianGasPrice != 0 { k.SetGasPrice(ctx, types.GasPrice{ - ChainId: chainID, - Prices: []uint64{tc.medianGasPrice}, - MedianIndex: 0, + ChainId: chainID, + Prices: []uint64{tc.medianGasPrice}, + PriorityFees: []uint64{tc.medianPriorityFee}, + MedianIndex: 0, }) // ensure median gas price is set - medianGasPrice, isFound := k.GetMedianGasPriceInUint(ctx, chainID) + medianGasPrice, medianPriorityFee, isFound := k.GetMedianGasValues(ctx, chainID) require.True(t, isFound) require.True(t, medianGasPrice.Equal(math.NewUint(tc.medianGasPrice))) + require.True(t, medianPriorityFee.Equal(math.NewUint(tc.medianPriorityFee))) } // set block timestamp diff --git a/x/crosschain/keeper/cctx_gateway_observers.go b/x/crosschain/keeper/cctx_gateway_observers.go index 18bf31afb8..c8ae0d718e 100644 --- a/x/crosschain/keeper/cctx_gateway_observers.go +++ b/x/crosschain/keeper/cctx_gateway_observers.go @@ -63,11 +63,12 @@ func (c CCTXGatewayObservers) InitiateOutbound( return err } } else { - gasPrice, found := c.crosschainKeeper.GetMedianGasPriceInUint(ctx, config.CCTX.GetCurrentOutboundParam().ReceiverChainId) + gasPrice, priorityFee, found := c.crosschainKeeper.GetMedianGasValues(ctx, config.CCTX.GetCurrentOutboundParam().ReceiverChainId) if !found { return fmt.Errorf("gasprice not found for %d", config.CCTX.GetCurrentOutboundParam().ReceiverChainId) } config.CCTX.GetCurrentOutboundParam().GasPrice = gasPrice.String() + config.CCTX.GetCurrentOutboundParam().GasPriorityFee = priorityFee.String() config.CCTX.GetCurrentOutboundParam().Amount = config.CCTX.InboundParams.Amount } return c.crosschainKeeper.SetObserverOutboundInfo(tmpCtx, outboundReceiverChainID, config.CCTX) diff --git a/x/crosschain/keeper/gas_payment.go b/x/crosschain/keeper/gas_payment.go index efac718932..a5a9b7d0fd 100644 --- a/x/crosschain/keeper/gas_payment.go +++ b/x/crosschain/keeper/gas_payment.go @@ -1,7 +1,6 @@ package keeper import ( - "errors" "fmt" "math/big" @@ -9,6 +8,7 @@ import ( "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" "github.com/zeta-chain/zetacore/cmd/zetacored/config" "github.com/zeta-chain/zetacore/pkg/coin" @@ -17,6 +17,19 @@ import ( observertypes "github.com/zeta-chain/zetacore/x/observer/types" ) +// ChainGasParams represents the parameters to calculate the fees for gas for a chain. +type ChainGasParams struct { + GasZRC20 ethcommon.Address + + GasLimit math.Uint + GasPrice math.Uint + + // PriorityFee (optional for EIP-1559) + PriorityFee math.Uint + + ProtocolFlatFee math.Uint +} + // PayGasAndUpdateCctx updates the outbound tx with the new amount after paying the gas fee // **Caller should feed temporary ctx into this function** // chainID is the outbound chain chain id , this can be receiver chain for regular transactions and sender-chain to reverted transactions @@ -43,42 +56,43 @@ func (k Keeper) PayGasAndUpdateCctx( // ChainGasParams returns the params to calculates the fees for gas for a chain // tha gas address, the gas limit, gas price and protocol flat fee are returned -func (k Keeper) ChainGasParams( - ctx sdk.Context, - chainID int64, -) (gasZRC20 ethcommon.Address, gasLimit, gasPrice, protocolFee math.Uint, err error) { - gasZRC20, err = k.fungibleKeeper.QuerySystemContractGasCoinZRC20(ctx, big.NewInt(chainID)) +func (k Keeper) ChainGasParams(ctx sdk.Context, chainID int64) (ChainGasParams, error) { + gasZRC20, err := k.fungibleKeeper.QuerySystemContractGasCoinZRC20(ctx, big.NewInt(chainID)) if err != nil { - return gasZRC20, gasLimit, gasPrice, protocolFee, err + return ChainGasParams{}, errors.Wrap(err, "unable to get system contract gas coin") } // get the gas limit - gasLimitQueried, err := k.fungibleKeeper.QueryGasLimit(ctx, gasZRC20) - if err != nil { - return gasZRC20, gasLimit, gasPrice, protocolFee, err - } - if gasLimitQueried == nil { - return gasZRC20, gasLimit, gasPrice, protocolFee, errors.New("gas limit is nil") + gasLimit, err := k.fungibleKeeper.QueryGasLimit(ctx, gasZRC20) + switch { + case err != nil: + return ChainGasParams{}, errors.Wrap(err, "unable to get gas limit") + case gasLimit == nil: + return ChainGasParams{}, types.ErrInvalidGasLimit } - gasLimit = math.NewUintFromBigInt(gasLimitQueried) // get the protocol flat fee - protocolFlatFeeQueried, err := k.fungibleKeeper.QueryProtocolFlatFee(ctx, gasZRC20) - if err != nil { - return gasZRC20, gasLimit, gasPrice, protocolFee, err - } - if protocolFlatFeeQueried == nil { - return gasZRC20, gasLimit, gasPrice, protocolFee, errors.New("protocol flat fee is nil") + protocolFlatFee, err := k.fungibleKeeper.QueryProtocolFlatFee(ctx, gasZRC20) + switch { + case err != nil: + return ChainGasParams{}, errors.Wrap(err, "unable to get protocol flat fee") + case protocolFlatFee == nil: + return ChainGasParams{}, cosmoserrors.Wrap(types.ErrInvalidGasAmount, "protocol flat fee is nil") } - protocolFee = math.NewUintFromBigInt(protocolFlatFeeQueried) // get the gas price - gasPrice, isFound := k.GetMedianGasPriceInUint(ctx, chainID) + gasPrice, priorityFee, isFound := k.GetMedianGasValues(ctx, chainID) if !isFound { - return gasZRC20, gasLimit, gasPrice, protocolFee, types.ErrUnableToGetGasPrice + return ChainGasParams{}, types.ErrUnableToGetGasPrice } - return + return ChainGasParams{ + GasZRC20: gasZRC20, + GasLimit: math.NewUintFromBigInt(gasLimit), + GasPrice: gasPrice, + PriorityFee: priorityFee, + ProtocolFlatFee: math.NewUintFromBigInt(protocolFlatFee), + }, nil } // PayGasNativeAndUpdateCctx updates the outbound tx with the new amount subtracting the gas fee @@ -102,13 +116,13 @@ func (k Keeper) PayGasNativeAndUpdateCctx( } // get gas params - _, gasLimit, gasPrice, protocolFlatFee, err := k.ChainGasParams(ctx, chainID) + gas, err := k.ChainGasParams(ctx, chainID) if err != nil { return cosmoserrors.Wrap(types.ErrCannotFindGasParams, err.Error()) } // calculate the final gas fee - outTxGasFee := gasLimit.Mul(gasPrice).Add(protocolFlatFee) + outTxGasFee := gas.GasLimit.Mul(gas.GasPrice).Add(gas.ProtocolFlatFee) // subtract the withdraw fee from the input amount if outTxGasFee.GT(inputAmount) { @@ -125,8 +139,9 @@ func (k Keeper) PayGasNativeAndUpdateCctx( // update cctx cctx.GetCurrentOutboundParam().Amount = newAmount - cctx.GetCurrentOutboundParam().GasLimit = gasLimit.Uint64() - cctx.GetCurrentOutboundParam().GasPrice = gasPrice.String() + cctx.GetCurrentOutboundParam().GasLimit = gas.GasLimit.Uint64() + cctx.GetCurrentOutboundParam().GasPrice = gas.GasPrice.String() + cctx.GetCurrentOutboundParam().GasPriorityFee = gas.PriorityFee.String() return nil } @@ -155,11 +170,11 @@ func (k Keeper) PayGasInERC20AndUpdateCctx( return observertypes.ErrSupportedChains } // get gas params - gasZRC20, gasLimit, gasPrice, protocolFlatFee, err := k.ChainGasParams(ctx, chainID) + gas, err := k.ChainGasParams(ctx, chainID) if err != nil { return cosmoserrors.Wrap(types.ErrCannotFindGasParams, err.Error()) } - outTxGasFee := gasLimit.Mul(gasPrice).Add(protocolFlatFee) + outTxGasFee := gas.GasLimit.Mul(gas.GasPrice).Add(gas.ProtocolFlatFee) // get address of the zrc20 fc, found := k.fungibleKeeper.GetForeignCoinFromAsset(ctx, cctx.InboundParams.Asset, chainID) if !found { @@ -183,7 +198,7 @@ func (k Keeper) PayGasInERC20AndUpdateCctx( ctx, outTxGasFee.BigInt(), zrc20, - gasZRC20, + gas.GasZRC20, ) if err != nil { // NOTE: this is the first method that fails when a liquidity pool is not set for the gas ZRC20, so we return a specific error @@ -236,7 +251,7 @@ func (k Keeper) PayGasInERC20AndUpdateCctx( types.ModuleAddressEVM, feeInZRC20, zrc20, - gasZRC20, + gas.GasZRC20, noEthereumTxEvent, ) if err != nil { @@ -262,19 +277,20 @@ func (k Keeper) PayGasInERC20AndUpdateCctx( } // burn the gas ZRC20 - err = k.fungibleKeeper.CallZRC20Burn(ctx, types.ModuleAddressEVM, gasZRC20, gasObtained, noEthereumTxEvent) + err = k.fungibleKeeper.CallZRC20Burn(ctx, types.ModuleAddressEVM, gas.GasZRC20, gasObtained, noEthereumTxEvent) if err != nil { return cosmoserrors.Wrap(fungibletypes.ErrContractCall, err.Error()) } ctx.Logger().Info("Burning gas ZRC20", - "zrc20", gasZRC20.Hex(), + "zrc20", gas.GasZRC20.Hex(), "amount", gasObtained, ) // update cctx cctx.GetCurrentOutboundParam().Amount = newAmount - cctx.GetCurrentOutboundParam().GasLimit = gasLimit.Uint64() - cctx.GetCurrentOutboundParam().GasPrice = gasPrice.String() + cctx.GetCurrentOutboundParam().GasLimit = gas.GasLimit.Uint64() + cctx.GetCurrentOutboundParam().GasPrice = gas.GasPrice.String() + cctx.GetCurrentOutboundParam().GasPriorityFee = gas.PriorityFee.String() return nil } @@ -314,14 +330,28 @@ func (k Keeper) PayGasInZetaAndUpdateCctx( } // get the gas price - gasPrice, isFound := k.GetMedianGasPriceInUint(ctx, chainID) + gasPrice, priorityFee, isFound := k.GetMedianGasValues(ctx, chainID) if !isFound { - return cosmoserrors.Wrap(types.ErrUnableToGetGasPrice, fmt.Sprintf(" chain %d | Identifiers : %s ", + return cosmoserrors.Wrapf(types.ErrUnableToGetGasPrice, + "chain %d; identifiers %q", chainID, - cctx.LogIdentifierForCCTX()), + cctx.LogIdentifierForCCTX(), + ) + } + // overpays gas price + const multiplier = 2 + gasPrice = gasPrice.MulUint64(multiplier) + priorityFee = priorityFee.MulUint64(multiplier) + + // should not happen + if priorityFee.GT(gasPrice) { + return cosmoserrors.Wrapf( + types.ErrInvalidGasAmount, + "priorityFee %s is greater than gasPrice %s", + priorityFee.String(), + gasPrice.String(), ) } - gasPrice = gasPrice.MulUint64(2) // overpays gas price by 2x // get the gas fee in gas token gasLimit := sdk.NewUint(cctx.GetCurrentOutboundParam().GasLimit) @@ -389,6 +419,7 @@ func (k Keeper) PayGasInZetaAndUpdateCctx( // Update the cctx cctx.GetCurrentOutboundParam().GasPrice = gasPrice.String() + cctx.GetCurrentOutboundParam().GasPriorityFee = priorityFee.String() cctx.GetCurrentOutboundParam().Amount = newAmount if cctx.ZetaFees.IsNil() { cctx.ZetaFees = feeInZeta diff --git a/x/crosschain/keeper/gas_price.go b/x/crosschain/keeper/gas_price.go index 84143cdc48..322aee53f5 100644 --- a/x/crosschain/keeper/gas_price.go +++ b/x/crosschain/keeper/gas_price.go @@ -7,35 +7,46 @@ import ( "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" + slicemath "github.com/zeta-chain/zetacore/pkg/math" "github.com/zeta-chain/zetacore/x/crosschain/types" ) // SetGasPrice set a specific gasPrice in the store from its index func (k Keeper) SetGasPrice(ctx sdk.Context, gasPrice types.GasPrice) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.GasPriceKey)) - b := k.cdc.MustMarshal(&gasPrice) gasPrice.Index = strconv.FormatInt(gasPrice.ChainId, 10) + b := k.cdc.MustMarshal(&gasPrice) store.Set(types.KeyPrefix(gasPrice.Index), b) } -// GetGasPrice returns a gasPrice from its index -func (k Keeper) GetGasPrice(ctx sdk.Context, chainID int64) (val types.GasPrice, found bool) { +// GetGasPrice returns a gasPrice from its index or false if it doesn't exist. +func (k Keeper) GetGasPrice(ctx sdk.Context, chainID int64) (types.GasPrice, bool) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.GasPriceKey)) + b := store.Get(types.KeyPrefix(strconv.FormatInt(chainID, 10))) if b == nil { - return val, false + return types.GasPrice{}, false } + + var val types.GasPrice k.cdc.MustUnmarshal(b, &val) + return val, true } -func (k Keeper) GetMedianGasPriceInUint(ctx sdk.Context, chainID int64) (sdk.Uint, bool) { - gasPrice, isFound := k.GetGasPrice(ctx, chainID) - if !isFound { - return math.ZeroUint(), isFound +// GetMedianGasValues returns *median* gas price and priority fee (for EIP-1559) from the store or false if it doesn't exist. +func (k Keeper) GetMedianGasValues(ctx sdk.Context, chainID int64) (math.Uint, math.Uint, bool) { + entity, found := k.GetGasPrice(ctx, chainID) + if !found { + return math.ZeroUint(), math.ZeroUint(), false } - mi := gasPrice.MedianIndex - return sdk.NewUint(gasPrice.Prices[mi]), true + + var ( + gasPrice = math.NewUint(entity.Prices[entity.MedianIndex]) + priorityFee = math.NewUint(slicemath.SliceMedianValue(entity.PriorityFees, false)) + ) + + return gasPrice, priorityFee, true } // RemoveGasPrice removes a gasPrice from the store diff --git a/x/crosschain/keeper/grpc_query_zeta_conversion_rate.go b/x/crosschain/keeper/grpc_query_zeta_conversion_rate.go index b1c1ca1dcf..6c8974db5d 100644 --- a/x/crosschain/keeper/grpc_query_zeta_conversion_rate.go +++ b/x/crosschain/keeper/grpc_query_zeta_conversion_rate.go @@ -25,7 +25,7 @@ func (k Keeper) ConvertGasToZeta( return nil, zetaObserverTypes.ErrSupportedChains } - medianGasPrice, isFound := k.GetMedianGasPriceInUint(ctx, chain.ChainId) + medianGasPrice, _, isFound := k.GetMedianGasValues(ctx, chain.ChainId) if !isFound { return nil, status.Error(codes.InvalidArgument, "invalid request: param chain") } diff --git a/x/crosschain/keeper/initiate_outbound.go b/x/crosschain/keeper/initiate_outbound.go index 7435517f2f..2a569cc8eb 100644 --- a/x/crosschain/keeper/initiate_outbound.go +++ b/x/crosschain/keeper/initiate_outbound.go @@ -1,8 +1,6 @@ package keeper import ( - "fmt" - cosmoserrors "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" @@ -26,21 +24,17 @@ func (k Keeper) InitiateOutbound(ctx sdk.Context, config InitiateOutboundConfig) receiverChainID := config.CCTX.GetCurrentOutboundParam().ReceiverChainId chainInfo, found := chains.GetChainFromChainID(receiverChainID, k.GetAuthorityKeeper().GetAdditionalChainList(ctx)) if !found { - return config.CCTX.CctxStatus.Status, cosmoserrors.Wrap( + return config.CCTX.CctxStatus.Status, cosmoserrors.Wrapf( types.ErrInitiatitingOutbound, - fmt.Sprintf( - "chain info not found for %d", receiverChainID, - ), + "chain info not found for %d", receiverChainID, ) } cctxGateway, found := ResolveCCTXGateway(chainInfo.CctxGateway, k) if !found { - return config.CCTX.CctxStatus.Status, cosmoserrors.Wrap( + return config.CCTX.CctxStatus.Status, cosmoserrors.Wrapf( types.ErrInitiatitingOutbound, - fmt.Sprintf( - "CCTXGateway not defined for receiver chain %d", receiverChainID, - ), + "CCTXGateway not defined for receiver chain %d", receiverChainID, ) } diff --git a/x/crosschain/keeper/msg_server_migrate_tss_funds.go b/x/crosschain/keeper/msg_server_migrate_tss_funds.go index 8656cf2e80..ed8c51b93d 100644 --- a/x/crosschain/keeper/msg_server_migrate_tss_funds.go +++ b/x/crosschain/keeper/msg_server_migrate_tss_funds.go @@ -89,7 +89,7 @@ func (k Keeper) MigrateTSSFundsForChain( ) error { // Always migrate to the latest TSS if multiple TSS addresses have been generated newTss := tssList[len(tssList)-1] - medianGasPrice, isFound := k.GetMedianGasPriceInUint(ctx, chainID) + medianGasPrice, priorityFee, isFound := k.GetMedianGasValues(ctx, chainID) if !isFound { return types.ErrUnableToGetGasPrice } @@ -136,6 +136,7 @@ func (k Keeper) MigrateTSSFundsForChain( TssNonce: 0, GasLimit: 1_000_000, GasPrice: medianGasPrice.MulUint64(2).String(), + GasPriorityFee: priorityFee.MulUint64(2).String(), Hash: "", BallotIndex: "", ObservedExternalHeight: 0, @@ -168,7 +169,6 @@ func (k Keeper) MigrateTSSFundsForChain( if err != nil { return err } - cctx.GetCurrentOutboundParam().GasPrice = multipliedGasPrice.String() evmFee := sdkmath.NewUint(cctx.GetCurrentOutboundParam().GasLimit).Mul(multipliedGasPrice) if evmFee.GT(amount) { return errorsmod.Wrap( @@ -182,6 +182,7 @@ func (k Keeper) MigrateTSSFundsForChain( ) } + cctx.GetCurrentOutboundParam().GasPrice = multipliedGasPrice.String() cctx.GetCurrentOutboundParam().Amount = amount.Sub( evmFee.Add(sdkmath.NewUintFromString(types.TSSMigrationBufferAmountEVM)), ) diff --git a/x/crosschain/keeper/msg_server_migrate_tss_funds_test.go b/x/crosschain/keeper/msg_server_migrate_tss_funds_test.go index 1dc23fd514..1896a35f59 100644 --- a/x/crosschain/keeper/msg_server_migrate_tss_funds_test.go +++ b/x/crosschain/keeper/msg_server_migrate_tss_funds_test.go @@ -61,13 +61,14 @@ func setupTssMigrationParams( Tss: currentTss.TssPubkey, }) k.SetGasPrice(ctx, crosschaintypes.GasPrice{ - Creator: "", - Index: "", - ChainId: chain.ChainId, - Signers: nil, - BlockNums: nil, - Prices: []uint64{100000, 100000, 100000}, - MedianIndex: 1, + Creator: "", + Index: "", + ChainId: chain.ChainId, + Signers: nil, + BlockNums: nil, + Prices: []uint64{100000, 100000, 100000}, + PriorityFees: []uint64{100, 300, 200}, + MedianIndex: 1, }) k.GetObserverKeeper().SetChainNonces(ctx, observertypes.ChainNonces{ ChainId: chain.ChainId, @@ -98,7 +99,7 @@ func TestKeeper_MigrateTSSFundsForChain(t *testing.T) { msgServer := keeper.NewMsgServerImpl(*k) indexString, _ := setupTssMigrationParams(zk, k, ctx, chain, amount, true, true) - gp, found := k.GetMedianGasPriceInUint(ctx, chain.ChainId) + gp, priorityFee, found := k.GetMedianGasValues(ctx, chain.ChainId) require.True(t, found) msg := crosschaintypes.MsgMigrateTssFunds{ Creator: admin, @@ -116,6 +117,7 @@ func TestKeeper_MigrateTSSFundsForChain(t *testing.T) { multipliedValue, err := gas.MultiplyGasPrice(gp, crosschaintypes.TssMigrationGasMultiplierEVM) require.NoError(t, err) require.Equal(t, multipliedValue.String(), cctx.GetCurrentOutboundParam().GasPrice) + require.Equal(t, priorityFee.MulUint64(2).String(), cctx.GetCurrentOutboundParam().GasPriorityFee) }) t.Run("test btc chain", func(t *testing.T) { @@ -131,7 +133,7 @@ func TestKeeper_MigrateTSSFundsForChain(t *testing.T) { msgServer := keeper.NewMsgServerImpl(*k) indexString, _ := setupTssMigrationParams(zk, k, ctx, chain, amount, true, true) - gp, found := k.GetMedianGasPriceInUint(ctx, chain.ChainId) + gp, priorityFee, found := k.GetMedianGasValues(ctx, chain.ChainId) require.True(t, found) msg := crosschaintypes.MsgMigrateTssFunds{ @@ -148,6 +150,7 @@ func TestKeeper_MigrateTSSFundsForChain(t *testing.T) { cctx, found := k.GetCrossChainTx(ctx, index) require.True(t, found) require.Equal(t, gp.MulUint64(2).String(), cctx.GetCurrentOutboundParam().GasPrice) + require.Equal(t, priorityFee.MulUint64(2).String(), cctx.GetCurrentOutboundParam().GasPriorityFee) }) } diff --git a/x/crosschain/keeper/msg_server_vote_gas_price.go b/x/crosschain/keeper/msg_server_vote_gas_price.go index aa56a73e26..2f8fbde036 100644 --- a/x/crosschain/keeper/msg_server_vote_gas_price.go +++ b/x/crosschain/keeper/msg_server_vote_gas_price.go @@ -4,12 +4,13 @@ import ( "context" "math/big" "sort" - "strconv" cosmoserrors "cosmossdk.io/errors" "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pkg/errors" + "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/x/crosschain/types" observertypes "github.com/zeta-chain/zetacore/x/observer/types" ) @@ -20,61 +21,80 @@ import ( // // Only observer validators are authorized to broadcast this message. func (k msgServer) VoteGasPrice( - goCtx context.Context, + cc context.Context, msg *types.MsgVoteGasPrice, ) (*types.MsgVoteGasPriceResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) + ctx := sdk.UnwrapSDKContext(cc) chain, found := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, msg.ChainId) if !found { - return nil, cosmoserrors.Wrapf(types.ErrUnsupportedChain, "ChainID: %d ", msg.ChainId) + return nil, cosmoserrors.Wrapf(types.ErrUnsupportedChain, "chain id %d", msg.ChainId) } + if ok := k.zetaObserverKeeper.IsNonTombstonedObserver(ctx, msg.Creator); !ok { return nil, observertypes.ErrNotObserver } gasPrice, isFound := k.GetGasPrice(ctx, chain.ChainId) if !isFound { - gasPrice = types.GasPrice{ - Creator: msg.Creator, - Index: strconv.FormatInt(chain.ChainId, 10), // TODO : Not needed index set at keeper - ChainId: chain.ChainId, - Prices: []uint64{msg.Price}, - BlockNums: []uint64{msg.BlockNumber}, - Signers: []string{msg.Creator}, - MedianIndex: 0, - } - } else { - signers := gasPrice.Signers - exist := false - for i, s := range signers { - if s == msg.Creator { // update existing entry - gasPrice.BlockNums[i] = msg.BlockNumber - gasPrice.Prices[i] = msg.Price - exist = true - break - } - } - if !exist { - gasPrice.Signers = append(gasPrice.Signers, msg.Creator) - gasPrice.BlockNums = append(gasPrice.BlockNums, msg.BlockNumber) - gasPrice.Prices = append(gasPrice.Prices, msg.Price) + return k.voteGasPrice(ctx, chain, types.GasPrice{ + Creator: msg.Creator, + ChainId: chain.ChainId, + Prices: []uint64{msg.Price}, + PriorityFees: []uint64{msg.PriorityFee}, + BlockNums: []uint64{msg.BlockNumber}, + Signers: []string{msg.Creator}, + }) + } + + // Now we either want to update the gas price or add a new entry + var exists bool + for i, s := range gasPrice.Signers { + if s != msg.Creator { + continue } - // recompute the median gas price - mi := medianOfArray(gasPrice.Prices) - // #nosec G115 always positive - gasPrice.MedianIndex = uint64(mi) + + // update existing entry + gasPrice.BlockNums[i] = msg.BlockNumber + gasPrice.Prices[i] = msg.Price + gasPrice.PriorityFees[i] = msg.PriorityFee + exists = true + break + } + + if !exists { + gasPrice.Signers = append(gasPrice.Signers, msg.Creator) + gasPrice.BlockNums = append(gasPrice.BlockNums, msg.BlockNumber) + gasPrice.Prices = append(gasPrice.Prices, msg.Price) + gasPrice.PriorityFees = append(gasPrice.PriorityFees, msg.PriorityFee) } - k.SetGasPrice(ctx, gasPrice) - chainIDBigINT := big.NewInt(chain.ChainId) - gasUsed, err := k.fungibleKeeper.SetGasPrice( - ctx, - chainIDBigINT, - math.NewUint(gasPrice.Prices[gasPrice.MedianIndex]).BigInt(), + // recompute the median gas price + mi := medianOfArray(gasPrice.Prices) + + // #nosec G115 always positive + gasPrice.MedianIndex = uint64(mi) + + return k.voteGasPrice(ctx, chain, gasPrice) +} + +func (k msgServer) voteGasPrice( + ctx sdk.Context, + chain chains.Chain, + entity types.GasPrice, +) (*types.MsgVoteGasPriceResponse, error) { + var ( + chainID = big.NewInt(chain.ChainId) + gasPrice = math.NewUint(entity.Prices[entity.MedianIndex]).BigInt() ) + + // set gas price in this module + k.SetGasPrice(ctx, entity) + + // set gas price in fungible keeper (also calls EVM) + gasUsed, err := k.fungibleKeeper.SetGasPrice(ctx, chainID, gasPrice) if err != nil { - return nil, err + return nil, errors.Wrap(err, "unable to set gas price in fungible keeper") } // reset the gas count diff --git a/x/crosschain/keeper/msg_server_vote_gas_price_test.go b/x/crosschain/keeper/msg_server_vote_gas_price_test.go index b5da0f0c1e..174c22753f 100644 --- a/x/crosschain/keeper/msg_server_vote_gas_price_test.go +++ b/x/crosschain/keeper/msg_server_vote_gas_price_test.go @@ -4,6 +4,7 @@ import ( "errors" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -101,13 +102,14 @@ func TestMsgServer_VoteGasPrice(t *testing.T) { gp, found := k.GetGasPrice(ctx, 5) require.True(t, found) require.Equal(t, types.GasPrice{ - Creator: creator, - Index: "5", - ChainId: 5, - Signers: []string{creator}, - BlockNums: []uint64{1}, - Prices: []uint64{1}, - MedianIndex: 0, + Creator: creator, + Index: "5", + ChainId: 5, + Signers: []string{creator}, + BlockNums: []uint64{1}, + Prices: []uint64{1}, + PriorityFees: []uint64{0}, + MedianIndex: 0, }, gp) }) @@ -129,11 +131,12 @@ func TestMsgServer_VoteGasPrice(t *testing.T) { creator := sample.AccAddress() k.SetGasPrice(ctx, types.GasPrice{ - Creator: creator, - ChainId: 5, - Signers: []string{creator}, - BlockNums: []uint64{1}, - Prices: []uint64{1}, + Creator: creator, + ChainId: 5, + Signers: []string{creator}, + BlockNums: []uint64{1}, + Prices: []uint64{1}, + PriorityFees: []uint64{0}, }) res, err := msgServer.VoteGasPrice(ctx, &types.MsgVoteGasPrice{ @@ -147,13 +150,14 @@ func TestMsgServer_VoteGasPrice(t *testing.T) { gp, found := k.GetGasPrice(ctx, 5) require.True(t, found) require.Equal(t, types.GasPrice{ - Creator: creator, - Index: "", - ChainId: 5, - Signers: []string{creator}, - BlockNums: []uint64{2}, - Prices: []uint64{2}, - MedianIndex: 0, + Creator: creator, + Index: "5", + ChainId: 5, + Signers: []string{creator}, + BlockNums: []uint64{2}, + Prices: []uint64{2}, + PriorityFees: []uint64{0}, + MedianIndex: 0, }, gp) }) @@ -175,10 +179,11 @@ func TestMsgServer_VoteGasPrice(t *testing.T) { creator := sample.AccAddress() k.SetGasPrice(ctx, types.GasPrice{ - Creator: creator, - ChainId: 5, - BlockNums: []uint64{1}, - Prices: []uint64{1}, + Creator: creator, + ChainId: 5, + BlockNums: []uint64{1}, + Prices: []uint64{1}, + PriorityFees: []uint64{0}, }) res, err := msgServer.VoteGasPrice(ctx, &types.MsgVoteGasPrice{ @@ -192,13 +197,69 @@ func TestMsgServer_VoteGasPrice(t *testing.T) { gp, found := k.GetGasPrice(ctx, 5) require.True(t, found) require.Equal(t, types.GasPrice{ + Creator: creator, + Index: "5", + ChainId: 5, + Signers: []string{creator}, + BlockNums: []uint64{1, 2}, + Prices: []uint64{1, 2}, + PriorityFees: []uint64{0, 0}, + MedianIndex: 1, + }, gp) + }) + + t.Run("works with a priority fee", func(t *testing.T) { + // ARRANGE + // Given a keeper with grpc server and some mocks + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + UseFungibleMock: true, + }) + + // Given a chain + chain := chains.Chain{ChainId: 5} + + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, chain.ChainId). + Return(chain, true) + + observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(true) + + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + fungibleMock.On("SetGasPrice", mock.Anything, mock.Anything, mock.Anything).Return(uint64(1), nil) + + msgServer := keeper.NewMsgServerImpl(*k) + creator := sample.AccAddress() + + // Given an existing gas price + _, err := msgServer.VoteGasPrice(ctx, &types.MsgVoteGasPrice{ + Creator: creator, + ChainId: chain.ChainId, + BlockNumber: 2, + Price: 2, + }) + require.NoError(t, err) + + // ACT + // When a new gas price is voted with a priority fee + _, err = msgServer.VoteGasPrice(ctx, &types.MsgVoteGasPrice{ Creator: creator, - Index: "", ChainId: 5, - Signers: []string{creator}, - BlockNums: []uint64{1, 2}, - Prices: []uint64{1, 2}, - MedianIndex: 1, - }, gp) + BlockNumber: 3, + Price: 3, + PriorityFee: 2, + }) + + // ASSERT + require.NoError(t, err) + + // Then gas prices should be updated as well as priority fee + gp, found := k.GetGasPrice(ctx, 5) + + assert.True(t, found) + assert.Equal(t, []string{creator}, gp.Signers) + assert.Equal(t, []uint64{3}, gp.BlockNums) + assert.Equal(t, []uint64{3}, gp.Prices) + assert.Equal(t, []uint64{2}, gp.PriorityFees) }) } diff --git a/x/crosschain/keeper/msg_server_whitelist_erc20.go b/x/crosschain/keeper/msg_server_whitelist_erc20.go index 8666bcbe82..7c9fe2363d 100644 --- a/x/crosschain/keeper/msg_server_whitelist_erc20.go +++ b/x/crosschain/keeper/msg_server_whitelist_erc20.go @@ -105,7 +105,7 @@ func (k msgServer) WhitelistERC20( if !found { return nil, errorsmod.Wrapf(types.ErrInvalidChainID, "chain params not found for chain id (%d)", msg.ChainId) } - medianGasPrice, isFound := k.GetMedianGasPriceInUint(ctx, msg.ChainId) + medianGasPrice, priorityFee, isFound := k.GetMedianGasValues(ctx, msg.ChainId) if !isFound { return nil, errorsmod.Wrapf( types.ErrUnableToGetGasPrice, @@ -113,7 +113,21 @@ func (k msgServer) WhitelistERC20( msg.ChainId, ) } - medianGasPrice = medianGasPrice.MulUint64(2) // overpays gas price by 2x + // overpays gas price by 2x + const multiplier = 2 + + medianGasPrice = medianGasPrice.MulUint64(multiplier) + priorityFee = priorityFee.MulUint64(multiplier) + + // should not happen + if priorityFee.GT(medianGasPrice) { + return nil, errorsmod.Wrapf( + types.ErrInvalidGasAmount, + "priorityFee %s is greater than median gasPrice %s", + priorityFee.String(), + medianGasPrice.String(), + ) + } // calculate the cctx index // we use the deployed zrc20 contract address to generate a unique index @@ -155,6 +169,7 @@ func (k msgServer) WhitelistERC20( TssNonce: 0, GasLimit: 100_000, GasPrice: medianGasPrice.String(), + GasPriorityFee: priorityFee.String(), Hash: "", BallotIndex: "", ObservedExternalHeight: 0, diff --git a/x/crosschain/types/cctx.go b/x/crosschain/types/cctx.go index a4080cc968..27b9b30968 100644 --- a/x/crosschain/types/cctx.go +++ b/x/crosschain/types/cctx.go @@ -196,6 +196,7 @@ func NewCCTX(ctx sdk.Context, msg MsgVoteInbound, tssPubkey string) (CrossChainT TssNonce: 0, GasLimit: msg.GasLimit, GasPrice: "", + GasPriorityFee: "", BallotIndex: "", ObservedExternalHeight: 0, Amount: sdkmath.ZeroUint(), diff --git a/x/crosschain/types/cross_chain_tx.pb.go b/x/crosschain/types/cross_chain_tx.pb.go index 79d61fd76b..5817c7b709 100644 --- a/x/crosschain/types/cross_chain_tx.pb.go +++ b/x/crosschain/types/cross_chain_tx.pb.go @@ -255,6 +255,7 @@ type OutboundParams struct { TssNonce uint64 `protobuf:"varint,5,opt,name=tss_nonce,json=tssNonce,proto3" json:"tss_nonce,omitempty"` GasLimit uint64 `protobuf:"varint,6,opt,name=gas_limit,json=gasLimit,proto3" json:"gas_limit,omitempty"` GasPrice string `protobuf:"bytes,7,opt,name=gas_price,json=gasPrice,proto3" json:"gas_price,omitempty"` + GasPriorityFee string `protobuf:"bytes,23,opt,name=gas_priority_fee,json=gasPriorityFee,proto3" json:"gas_priority_fee,omitempty"` // the above are commands for zetaclients // the following fields are used when the outbound tx is mined Hash string `protobuf:"bytes,8,opt,name=hash,proto3" json:"hash,omitempty"` @@ -342,6 +343,13 @@ func (m *OutboundParams) GetGasPrice() string { return "" } +func (m *OutboundParams) GetGasPriorityFee() string { + if m != nil { + return m.GasPriorityFee + } + return "" +} + func (m *OutboundParams) GetHash() string { if m != nil { return m.Hash @@ -559,74 +567,76 @@ func init() { } var fileDescriptor_d4c1966807fb5cb2 = []byte{ - // 1072 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcd, 0x6e, 0xdb, 0x46, - 0x10, 0x16, 0x23, 0x59, 0x96, 0x46, 0xbf, 0x59, 0x2b, 0x06, 0xeb, 0x22, 0x8a, 0xab, 0x22, 0x89, - 0x12, 0xd4, 0x14, 0xe2, 0x5c, 0x8a, 0xde, 0x6c, 0x23, 0x4e, 0x8c, 0x34, 0x89, 0xc1, 0xd8, 0x3d, - 0xe4, 0x50, 0x76, 0x45, 0x8e, 0xa9, 0x85, 0x25, 0xae, 0xca, 0x5d, 0x19, 0x74, 0xd0, 0x87, 0xe8, - 0x43, 0xf4, 0xd0, 0x63, 0x9f, 0xa0, 0xe7, 0xdc, 0x9a, 0x63, 0xd1, 0x83, 0xd1, 0xda, 0x6f, 0xd0, - 0x27, 0x28, 0x76, 0x97, 0x94, 0x2c, 0xc3, 0xb0, 0xd3, 0xb4, 0x27, 0xcd, 0x7c, 0xb3, 0xfb, 0xcd, - 0x68, 0xf6, 0x9b, 0x5d, 0xc2, 0xfa, 0x5b, 0x94, 0xd4, 0x1f, 0x50, 0x16, 0xf5, 0xb4, 0xc5, 0x63, - 0xec, 0xf9, 0x31, 0x17, 0xc2, 0x60, 0xda, 0xf4, 0xb4, 0xed, 0xc9, 0xc4, 0x19, 0xc7, 0x5c, 0x72, - 0x72, 0x7b, 0xba, 0xc7, 0xc9, 0xf6, 0x38, 0xb3, 0x3d, 0x2b, 0xad, 0x90, 0x87, 0x5c, 0xaf, 0xec, - 0x29, 0xcb, 0x6c, 0x5a, 0xb9, 0x77, 0x49, 0xa2, 0xf1, 0x61, 0xd8, 0xf3, 0xb9, 0x4a, 0xc3, 0x59, - 0x64, 0xd6, 0x75, 0x7e, 0x29, 0x40, 0x6d, 0x27, 0xea, 0xf3, 0x49, 0x14, 0xec, 0xd2, 0x98, 0x8e, - 0x04, 0x59, 0x86, 0xa2, 0xc0, 0x28, 0xc0, 0xd8, 0xb6, 0x56, 0xad, 0x6e, 0xd9, 0x4d, 0x3d, 0x72, - 0x0f, 0x1a, 0xc6, 0x4a, 0xeb, 0x63, 0x81, 0x7d, 0x63, 0xd5, 0xea, 0xe6, 0xdd, 0x9a, 0x81, 0xb7, - 0x14, 0xba, 0x13, 0x90, 0x4f, 0xa1, 0x2c, 0x13, 0x8f, 0xc7, 0x2c, 0x64, 0x91, 0x9d, 0xd7, 0x14, - 0x25, 0x99, 0xbc, 0xd2, 0x3e, 0xd9, 0x84, 0xb2, 0x4a, 0xee, 0xc9, 0xe3, 0x31, 0xda, 0x85, 0x55, - 0xab, 0x5b, 0x5f, 0xbf, 0xeb, 0x5c, 0xf2, 0xff, 0xc6, 0x87, 0xa1, 0xa3, 0xab, 0xdc, 0xe2, 0x2c, - 0xda, 0x3b, 0x1e, 0xa3, 0x5b, 0xf2, 0x53, 0x8b, 0xb4, 0x60, 0x81, 0x0a, 0x81, 0xd2, 0x5e, 0xd0, - 0xe4, 0xc6, 0x21, 0x4f, 0xa1, 0x48, 0x47, 0x7c, 0x12, 0x49, 0xbb, 0xa8, 0xe0, 0xcd, 0xde, 0xbb, - 0x93, 0x3b, 0xb9, 0x3f, 0x4e, 0xee, 0xdc, 0x0f, 0x99, 0x1c, 0x4c, 0xfa, 0x8e, 0xcf, 0x47, 0x3d, - 0x9f, 0x8b, 0x11, 0x17, 0xe9, 0xcf, 0x9a, 0x08, 0x0e, 0x7b, 0xaa, 0x0e, 0xe1, 0xec, 0xb3, 0x48, - 0xba, 0xe9, 0x76, 0xf2, 0x39, 0xd4, 0x78, 0x5f, 0x60, 0x7c, 0x84, 0x81, 0x37, 0xa0, 0x62, 0x60, - 0x2f, 0xea, 0x34, 0xd5, 0x0c, 0x7c, 0x46, 0xc5, 0x80, 0x7c, 0x09, 0xf6, 0x74, 0x11, 0x26, 0x12, - 0xe3, 0x88, 0x0e, 0xbd, 0x01, 0xb2, 0x70, 0x20, 0xed, 0xd2, 0xaa, 0xd5, 0x2d, 0xb8, 0xcb, 0x59, - 0xfc, 0x49, 0x1a, 0x7e, 0xa6, 0xa3, 0xe4, 0x33, 0xa8, 0xf6, 0xe9, 0x70, 0xc8, 0xa5, 0xc7, 0xa2, - 0x00, 0x13, 0xbb, 0xac, 0xd9, 0x2b, 0x06, 0xdb, 0x51, 0x10, 0x59, 0x87, 0x5b, 0x07, 0x2c, 0xa2, - 0x43, 0xf6, 0x16, 0x03, 0x4f, 0xb5, 0x24, 0x63, 0x06, 0xcd, 0xbc, 0x34, 0x0d, 0xbe, 0x41, 0x49, - 0x53, 0x5a, 0x06, 0xcb, 0x32, 0xf1, 0xd2, 0x08, 0x95, 0x8c, 0x47, 0x9e, 0x90, 0x54, 0x4e, 0x84, - 0x5d, 0xd1, 0x5d, 0x7e, 0xec, 0x5c, 0xa9, 0x22, 0x67, 0x2f, 0xd9, 0x3e, 0xb7, 0xf7, 0xb5, 0xde, - 0xea, 0xb6, 0xe4, 0x25, 0x68, 0xe7, 0x7b, 0xa8, 0xab, 0xc4, 0x1b, 0xbe, 0xaf, 0xfa, 0xc5, 0xa2, - 0x90, 0x78, 0xb0, 0x44, 0xfb, 0x3c, 0x96, 0x59, 0xb9, 0xe9, 0x41, 0x58, 0x1f, 0x77, 0x10, 0x37, - 0x53, 0x2e, 0x9d, 0x44, 0x33, 0x75, 0xfe, 0x5a, 0x80, 0xfa, 0xab, 0x89, 0x3c, 0x2f, 0xd3, 0x15, - 0x28, 0xc5, 0xe8, 0x23, 0x3b, 0x9a, 0x0a, 0x75, 0xea, 0x93, 0x07, 0xd0, 0xcc, 0x6c, 0x23, 0xd6, - 0x9d, 0x4c, 0xab, 0x8d, 0x0c, 0xcf, 0xd4, 0x3a, 0x27, 0xc8, 0xfc, 0xc7, 0x09, 0x72, 0x26, 0xbd, - 0xc2, 0x7f, 0x93, 0x9e, 0x1a, 0x1d, 0x21, 0xbc, 0x88, 0x47, 0x3e, 0x6a, 0x75, 0x17, 0xdc, 0x92, - 0x14, 0xe2, 0xa5, 0xf2, 0x55, 0x30, 0xa4, 0xc2, 0x1b, 0xb2, 0x11, 0x33, 0x1a, 0x2f, 0xb8, 0xa5, - 0x90, 0x8a, 0xaf, 0x95, 0x9f, 0x05, 0xc7, 0x31, 0xf3, 0x31, 0x15, 0xac, 0x0a, 0xee, 0x2a, 0x9f, - 0x10, 0x28, 0x68, 0x21, 0x97, 0x34, 0xae, 0xed, 0x0f, 0x91, 0xe1, 0x55, 0x1a, 0x87, 0x2b, 0x35, - 0xfe, 0x09, 0xa8, 0xe4, 0xde, 0x44, 0x60, 0x60, 0xb7, 0xf4, 0xca, 0xc5, 0x90, 0x8a, 0x7d, 0x81, - 0x01, 0xf9, 0x16, 0x96, 0xf0, 0xe0, 0x00, 0x7d, 0xc9, 0x8e, 0xd0, 0x9b, 0x95, 0x7c, 0x4b, 0x37, - 0xce, 0x49, 0x1b, 0x77, 0xef, 0x03, 0x1a, 0xb7, 0xa3, 0x94, 0x32, 0xa5, 0x7a, 0x9a, 0xfd, 0x57, - 0xe7, 0x22, 0xbf, 0xe9, 0xd7, 0xb2, 0xae, 0x62, 0x6e, 0xbd, 0x69, 0xdc, 0x6d, 0x00, 0xd5, 0xf2, - 0xf1, 0xa4, 0x7f, 0x88, 0xc7, 0x7a, 0x56, 0xca, 0xae, 0x3a, 0x84, 0x5d, 0x0d, 0x5c, 0x31, 0x56, - 0xd5, 0xff, 0x7b, 0xac, 0x7e, 0xb3, 0xa0, 0x68, 0x4c, 0xb2, 0x01, 0xc5, 0x34, 0x8b, 0xa5, 0xb3, - 0x3c, 0xb8, 0x26, 0xcb, 0x96, 0x2f, 0x93, 0x94, 0x3b, 0xdd, 0x48, 0xee, 0x42, 0xdd, 0x58, 0xde, - 0x08, 0x85, 0xa0, 0x21, 0xea, 0x01, 0x28, 0xbb, 0x35, 0x83, 0xbe, 0x30, 0x20, 0x79, 0x04, 0xad, - 0x21, 0x15, 0x72, 0x7f, 0x1c, 0x50, 0x89, 0x9e, 0x64, 0x23, 0x14, 0x92, 0x8e, 0xc6, 0x7a, 0x12, - 0xf2, 0xee, 0xd2, 0x2c, 0xb6, 0x97, 0x85, 0x48, 0x17, 0x1a, 0x4c, 0x6c, 0xa8, 0x11, 0x75, 0xf1, - 0x60, 0x12, 0x05, 0x18, 0x68, 0xd9, 0x97, 0xdc, 0x8b, 0x70, 0xe7, 0xd7, 0x3c, 0x54, 0xb7, 0x54, - 0x95, 0x7a, 0xd8, 0xf6, 0x12, 0x62, 0xc3, 0xa2, 0x1f, 0x23, 0x95, 0x3c, 0x1b, 0xd9, 0xcc, 0x55, - 0x77, 0xba, 0xd1, 0xa1, 0xa9, 0xd2, 0x38, 0xe4, 0x3b, 0x28, 0xeb, 0xfb, 0xe4, 0x00, 0x51, 0x98, - 0xdb, 0x7e, 0x73, 0xeb, 0x5f, 0xce, 0xd6, 0xdf, 0x27, 0x77, 0x9a, 0xc7, 0x74, 0x34, 0xfc, 0xaa, - 0x33, 0x65, 0xea, 0xb8, 0x25, 0x65, 0x6f, 0x23, 0x0a, 0x72, 0x1f, 0x1a, 0x31, 0x0e, 0xe9, 0x31, - 0x06, 0xd3, 0x3e, 0xe9, 0xe7, 0xc3, 0xad, 0xa7, 0x70, 0xd6, 0xa8, 0x6d, 0xa8, 0xf8, 0xbe, 0x4c, - 0xb2, 0xd3, 0x57, 0xa3, 0x54, 0xb9, 0xfc, 0xa6, 0x38, 0x77, 0x2e, 0xe9, 0x99, 0x80, 0x3f, 0x3d, - 0x1f, 0xf2, 0x1a, 0xea, 0xcc, 0x3c, 0xb7, 0xde, 0x58, 0x5f, 0x64, 0x7a, 0xf2, 0x2a, 0xeb, 0x5f, - 0x5c, 0x43, 0x35, 0xf7, 0x46, 0xbb, 0x35, 0x36, 0xf7, 0x64, 0x7f, 0x03, 0x0d, 0x9e, 0xde, 0x8e, - 0x19, 0x2b, 0xac, 0xe6, 0xbb, 0x95, 0xf5, 0xb5, 0x6b, 0x58, 0xe7, 0xef, 0x54, 0xb7, 0xce, 0xe7, - 0xfc, 0x87, 0x3f, 0x00, 0xcc, 0xa4, 0x45, 0x08, 0xd4, 0x77, 0x31, 0x0a, 0x58, 0x14, 0xa6, 0xc5, - 0x34, 0x73, 0x64, 0x09, 0x1a, 0x29, 0x96, 0x51, 0x35, 0x2d, 0x72, 0x13, 0x6a, 0x99, 0xf7, 0x82, - 0x45, 0x18, 0x34, 0xf3, 0x0a, 0x4a, 0xd7, 0xb9, 0x78, 0x84, 0xb1, 0x6c, 0x16, 0x48, 0x15, 0x4a, - 0xc6, 0xc6, 0xa0, 0xb9, 0x40, 0x2a, 0xb0, 0xb8, 0x61, 0xae, 0xfd, 0x66, 0x71, 0xa5, 0xf0, 0xf3, - 0x4f, 0x6d, 0xeb, 0xe1, 0x73, 0x68, 0x5d, 0x36, 0x3e, 0xa4, 0x09, 0xd5, 0x97, 0x5c, 0x6e, 0x67, - 0x8f, 0x60, 0x33, 0x47, 0x6a, 0x50, 0x9e, 0xb9, 0x96, 0x62, 0x7e, 0x92, 0xa0, 0x3f, 0x51, 0x64, - 0x37, 0x0c, 0xd9, 0xe6, 0xf3, 0x77, 0xa7, 0x6d, 0xeb, 0xfd, 0x69, 0xdb, 0xfa, 0xf3, 0xb4, 0x6d, - 0xfd, 0x78, 0xd6, 0xce, 0xbd, 0x3f, 0x6b, 0xe7, 0x7e, 0x3f, 0x6b, 0xe7, 0xde, 0x3c, 0x3a, 0xa7, - 0x24, 0xd5, 0xa3, 0xb5, 0x0b, 0x5f, 0x4d, 0xc9, 0xf9, 0x0f, 0x34, 0x2d, 0xac, 0x7e, 0x51, 0x7f, - 0x3b, 0x3d, 0xfe, 0x27, 0x00, 0x00, 0xff, 0xff, 0x77, 0x35, 0xca, 0x79, 0xce, 0x09, 0x00, 0x00, + // 1100 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcd, 0x72, 0x13, 0x47, + 0x10, 0xd6, 0x22, 0x21, 0x4b, 0xad, 0xbf, 0x65, 0x2c, 0x9c, 0x8d, 0x53, 0x08, 0x47, 0x29, 0x40, + 0x50, 0x41, 0x2a, 0xcc, 0x25, 0x95, 0x9b, 0xed, 0xc2, 0xe0, 0x10, 0xc0, 0xb5, 0x98, 0x1c, 0x38, + 0x64, 0x33, 0xda, 0x6d, 0xad, 0xa6, 0x2c, 0xed, 0x28, 0x3b, 0x23, 0xd7, 0x8a, 0xca, 0x43, 0x24, + 0xef, 0x90, 0x43, 0x8e, 0x79, 0x82, 0x9c, 0xb9, 0x85, 0x63, 0x2a, 0x07, 0x2a, 0x85, 0xdf, 0x20, + 0x4f, 0x90, 0x9a, 0x99, 0x5d, 0xc9, 0x72, 0xb9, 0x6c, 0x42, 0x72, 0x52, 0xf7, 0xd7, 0x33, 0x5f, + 0xb7, 0x7a, 0xbe, 0x9e, 0x59, 0xd8, 0x7c, 0x85, 0x92, 0xfa, 0x43, 0xca, 0xa2, 0x9e, 0xb6, 0x78, + 0x8c, 0x3d, 0x3f, 0xe6, 0x42, 0x18, 0x4c, 0x9b, 0x9e, 0xb6, 0x3d, 0x99, 0x74, 0x27, 0x31, 0x97, + 0x9c, 0x5c, 0x9b, 0xef, 0xe9, 0x66, 0x7b, 0xba, 0x8b, 0x3d, 0xeb, 0xcd, 0x90, 0x87, 0x5c, 0xaf, + 0xec, 0x29, 0xcb, 0x6c, 0x5a, 0xbf, 0x79, 0x46, 0xa2, 0xc9, 0x61, 0xd8, 0xf3, 0xb9, 0x4a, 0xc3, + 0x59, 0x64, 0xd6, 0xb5, 0x7f, 0x2d, 0x40, 0x6d, 0x2f, 0xea, 0xf3, 0x69, 0x14, 0xec, 0xd3, 0x98, + 0x8e, 0x05, 0x59, 0x83, 0xa2, 0xc0, 0x28, 0xc0, 0xd8, 0xb1, 0x36, 0xac, 0x4e, 0xd9, 0x4d, 0x3d, + 0x72, 0x13, 0x1a, 0xc6, 0x4a, 0xeb, 0x63, 0x81, 0x73, 0x69, 0xc3, 0xea, 0xe4, 0xdd, 0x9a, 0x81, + 0x77, 0x14, 0xba, 0x17, 0x90, 0x4f, 0xa0, 0x2c, 0x13, 0x8f, 0xc7, 0x2c, 0x64, 0x91, 0x93, 0xd7, + 0x14, 0x25, 0x99, 0x3c, 0xd3, 0x3e, 0xd9, 0x86, 0xb2, 0x4a, 0xee, 0xc9, 0xd9, 0x04, 0x9d, 0xc2, + 0x86, 0xd5, 0xa9, 0x6f, 0xde, 0xe8, 0x9e, 0xf1, 0xff, 0x26, 0x87, 0x61, 0x57, 0x57, 0xb9, 0xc3, + 0x59, 0x74, 0x30, 0x9b, 0xa0, 0x5b, 0xf2, 0x53, 0x8b, 0x34, 0xe1, 0x32, 0x15, 0x02, 0xa5, 0x73, + 0x59, 0x93, 0x1b, 0x87, 0x3c, 0x84, 0x22, 0x1d, 0xf3, 0x69, 0x24, 0x9d, 0xa2, 0x82, 0xb7, 0x7b, + 0xaf, 0xdf, 0x5e, 0xcf, 0xfd, 0xf9, 0xf6, 0xfa, 0xad, 0x90, 0xc9, 0xe1, 0xb4, 0xdf, 0xf5, 0xf9, + 0xb8, 0xe7, 0x73, 0x31, 0xe6, 0x22, 0xfd, 0xb9, 0x2b, 0x82, 0xc3, 0x9e, 0xaa, 0x43, 0x74, 0x5f, + 0xb0, 0x48, 0xba, 0xe9, 0x76, 0xf2, 0x19, 0xd4, 0x78, 0x5f, 0x60, 0x7c, 0x84, 0x81, 0x37, 0xa4, + 0x62, 0xe8, 0xac, 0xe8, 0x34, 0xd5, 0x0c, 0x7c, 0x44, 0xc5, 0x90, 0x7c, 0x01, 0xce, 0x7c, 0x11, + 0x26, 0x12, 0xe3, 0x88, 0x8e, 0xbc, 0x21, 0xb2, 0x70, 0x28, 0x9d, 0xd2, 0x86, 0xd5, 0x29, 0xb8, + 0x6b, 0x59, 0xfc, 0x41, 0x1a, 0x7e, 0xa4, 0xa3, 0xe4, 0x53, 0xa8, 0xf6, 0xe9, 0x68, 0xc4, 0xa5, + 0xc7, 0xa2, 0x00, 0x13, 0xa7, 0xac, 0xd9, 0x2b, 0x06, 0xdb, 0x53, 0x10, 0xd9, 0x84, 0xab, 0x03, + 0x16, 0xd1, 0x11, 0x7b, 0x85, 0x81, 0xa7, 0x5a, 0x92, 0x31, 0x83, 0x66, 0x5e, 0x9d, 0x07, 0x5f, + 0xa2, 0xa4, 0x29, 0x2d, 0x83, 0x35, 0x99, 0x78, 0x69, 0x84, 0x4a, 0xc6, 0x23, 0x4f, 0x48, 0x2a, + 0xa7, 0xc2, 0xa9, 0xe8, 0x2e, 0xdf, 0xef, 0x9e, 0xab, 0xa2, 0xee, 0x41, 0xb2, 0x7b, 0x62, 0xef, + 0x73, 0xbd, 0xd5, 0x6d, 0xca, 0x33, 0xd0, 0xf6, 0xf7, 0x50, 0x57, 0x89, 0xb7, 0x7c, 0x5f, 0xf5, + 0x8b, 0x45, 0x21, 0xf1, 0x60, 0x95, 0xf6, 0x79, 0x2c, 0xb3, 0x72, 0xd3, 0x83, 0xb0, 0x3e, 0xec, + 0x20, 0xae, 0xa4, 0x5c, 0x3a, 0x89, 0x66, 0x6a, 0xff, 0x54, 0x84, 0xfa, 0xb3, 0xa9, 0x3c, 0x29, + 0xd3, 0x75, 0x28, 0xc5, 0xe8, 0x23, 0x3b, 0x9a, 0x0b, 0x75, 0xee, 0x93, 0xdb, 0x60, 0x67, 0xb6, + 0x11, 0xeb, 0x5e, 0xa6, 0xd5, 0x46, 0x86, 0x67, 0x6a, 0x5d, 0x12, 0x64, 0xfe, 0xc3, 0x04, 0xb9, + 0x90, 0x5e, 0xe1, 0xbf, 0x49, 0x4f, 0x8d, 0x8e, 0x10, 0x5e, 0xc4, 0x23, 0x1f, 0xb5, 0xba, 0x0b, + 0x6e, 0x49, 0x0a, 0xf1, 0x54, 0xf9, 0x2a, 0x18, 0x52, 0xe1, 0x8d, 0xd8, 0x98, 0x19, 0x8d, 0x17, + 0xdc, 0x52, 0x48, 0xc5, 0xd7, 0xca, 0xcf, 0x82, 0x93, 0x98, 0xf9, 0x98, 0x0a, 0x56, 0x05, 0xf7, + 0x95, 0x4f, 0x3a, 0x60, 0xa7, 0x41, 0x1e, 0x33, 0x39, 0xf3, 0x06, 0x88, 0xce, 0x47, 0x7a, 0x4d, + 0xdd, 0xac, 0xd1, 0xf0, 0x2e, 0x22, 0x21, 0x50, 0xd0, 0x92, 0x2f, 0xe9, 0xa8, 0xb6, 0xdf, 0x47, + 0xb0, 0xe7, 0x4d, 0x03, 0x9c, 0x3b, 0x0d, 0x1f, 0x83, 0x2a, 0xd3, 0x9b, 0x0a, 0x0c, 0x9c, 0xa6, + 0x5e, 0xb9, 0x12, 0x52, 0xf1, 0x42, 0x60, 0x40, 0xbe, 0x85, 0x55, 0x1c, 0x0c, 0xd0, 0x97, 0xec, + 0x08, 0xbd, 0xc5, 0x9f, 0xbb, 0xaa, 0x5b, 0xdc, 0x4d, 0x5b, 0x7c, 0xf3, 0x3d, 0x5a, 0xbc, 0xa7, + 0x34, 0x35, 0xa7, 0x7a, 0x98, 0x75, 0xa5, 0x7b, 0x9a, 0xdf, 0x74, 0x76, 0x4d, 0x57, 0xb1, 0xb4, + 0xde, 0xb4, 0xf8, 0x1a, 0x80, 0x3a, 0x9c, 0xc9, 0xb4, 0x7f, 0x88, 0x33, 0x3d, 0x55, 0x65, 0x57, + 0x1d, 0xd7, 0xbe, 0x06, 0xce, 0x19, 0xc0, 0xea, 0xff, 0x3c, 0x80, 0x5f, 0x15, 0x4a, 0x35, 0xbb, + 0xd9, 0xfe, 0xdd, 0x82, 0xa2, 0x01, 0xc8, 0x16, 0x14, 0xd3, 0x5c, 0x96, 0xce, 0x75, 0xfb, 0x82, + 0x5c, 0x3b, 0xbe, 0x4c, 0xd2, 0x0c, 0xe9, 0x46, 0x72, 0x03, 0xea, 0xc6, 0xf2, 0xc6, 0x28, 0x04, + 0x0d, 0x51, 0x0f, 0x4c, 0xd9, 0xad, 0x19, 0xf4, 0x89, 0x01, 0xc9, 0x3d, 0x68, 0x8e, 0xa8, 0x90, + 0x2f, 0x26, 0x01, 0x95, 0xe8, 0x49, 0x36, 0x46, 0x21, 0xe9, 0x78, 0xa2, 0x27, 0x27, 0xef, 0xae, + 0x2e, 0x62, 0x07, 0x59, 0x88, 0x74, 0xa0, 0xc1, 0xc4, 0x96, 0x1a, 0x69, 0x17, 0x07, 0xd3, 0x28, + 0xc0, 0x40, 0x8f, 0x49, 0xc9, 0x3d, 0x0d, 0xb7, 0x7f, 0xcb, 0x43, 0x75, 0x47, 0x55, 0xa9, 0x87, + 0xf3, 0x20, 0x21, 0x0e, 0xac, 0xf8, 0x31, 0x52, 0xc9, 0xb3, 0x11, 0xcf, 0x5c, 0xf5, 0x06, 0x18, + 0x35, 0x9a, 0x2a, 0x8d, 0x43, 0xbe, 0x83, 0xb2, 0xbe, 0x7f, 0x06, 0x88, 0xc2, 0xbc, 0x0e, 0xdb, + 0x3b, 0xff, 0x72, 0x16, 0xff, 0x7e, 0x7b, 0xdd, 0x9e, 0xd1, 0xf1, 0xe8, 0xcb, 0xf6, 0x9c, 0xa9, + 0xed, 0x96, 0x94, 0xbd, 0x8b, 0x28, 0xc8, 0x2d, 0x68, 0xc4, 0x38, 0xa2, 0x33, 0x0c, 0xe6, 0x7d, + 0x2a, 0x9a, 0x49, 0x4a, 0xe1, 0xac, 0x51, 0xbb, 0x50, 0xf1, 0x7d, 0x99, 0x64, 0x1a, 0x50, 0x03, + 0x55, 0x39, 0xfb, 0x66, 0x39, 0x71, 0x2e, 0xe9, 0x99, 0x80, 0x3f, 0x3f, 0x1f, 0xf2, 0x1c, 0xea, + 0xcc, 0x3c, 0xcf, 0xde, 0x44, 0x5f, 0x7c, 0x7a, 0xfe, 0x2a, 0x9b, 0x9f, 0x5f, 0x40, 0xb5, 0xf4, + 0xa6, 0xbb, 0x35, 0xb6, 0xf4, 0xc4, 0x7f, 0x03, 0x0d, 0x9e, 0xde, 0xa6, 0x19, 0x2b, 0x6c, 0xe4, + 0x3b, 0x95, 0xcd, 0xbb, 0x17, 0xb0, 0x2e, 0xdf, 0xc1, 0x6e, 0x9d, 0x2f, 0xf9, 0x77, 0x7e, 0x00, + 0x58, 0x48, 0x8b, 0x10, 0xa8, 0xef, 0x63, 0x14, 0xb0, 0x28, 0x4c, 0x8b, 0xb1, 0x73, 0x64, 0x15, + 0x1a, 0x29, 0x96, 0x51, 0xd9, 0x16, 0xb9, 0x02, 0xb5, 0xcc, 0x7b, 0xc2, 0x22, 0x0c, 0xec, 0xbc, + 0x82, 0xd2, 0x75, 0x2e, 0x1e, 0x61, 0x2c, 0xed, 0x02, 0xa9, 0x42, 0xc9, 0xd8, 0x18, 0xd8, 0x97, + 0x49, 0x05, 0x56, 0xb6, 0xcc, 0x33, 0x61, 0x17, 0xd7, 0x0b, 0xbf, 0xfc, 0xdc, 0xb2, 0xee, 0x3c, + 0x86, 0xe6, 0x59, 0x43, 0x44, 0x6c, 0xa8, 0x3e, 0xe5, 0x72, 0x37, 0x7b, 0x34, 0xed, 0x1c, 0xa9, + 0x41, 0x79, 0xe1, 0x5a, 0x8a, 0xf9, 0x41, 0x82, 0xfe, 0x54, 0x91, 0x5d, 0x32, 0x64, 0xdb, 0x8f, + 0x5f, 0xbf, 0x6b, 0x59, 0x6f, 0xde, 0xb5, 0xac, 0xbf, 0xde, 0xb5, 0xac, 0x1f, 0x8f, 0x5b, 0xb9, + 0x37, 0xc7, 0xad, 0xdc, 0x1f, 0xc7, 0xad, 0xdc, 0xcb, 0x7b, 0x27, 0x94, 0xa4, 0x7a, 0x74, 0xf7, + 0xd4, 0x57, 0x56, 0x72, 0xf2, 0x83, 0x4e, 0x0b, 0xab, 0x5f, 0xd4, 0xdf, 0x5a, 0xf7, 0xff, 0x09, + 0x00, 0x00, 0xff, 0xff, 0xea, 0x6a, 0x48, 0x57, 0xfe, 0x09, 0x00, 0x00, } func (m *InboundParams) Marshal() (dAtA []byte, err error) { @@ -775,6 +785,15 @@ func (m *OutboundParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.GasPriorityFee) > 0 { + i -= len(m.GasPriorityFee) + copy(dAtA[i:], m.GasPriorityFee) + i = encodeVarintCrossChainTx(dAtA, i, uint64(len(m.GasPriorityFee))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xba + } if m.EffectiveGasLimit != 0 { i = encodeVarintCrossChainTx(dAtA, i, uint64(m.EffectiveGasLimit)) i-- @@ -1143,6 +1162,10 @@ func (m *OutboundParams) Size() (n int) { if m.EffectiveGasLimit != 0 { n += 2 + sovCrossChainTx(uint64(m.EffectiveGasLimit)) } + l = len(m.GasPriorityFee) + if l > 0 { + n += 2 + l + sovCrossChainTx(uint64(l)) + } return n } @@ -2043,6 +2066,38 @@ func (m *OutboundParams) Unmarshal(dAtA []byte) error { break } } + case 23: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GasPriorityFee", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCrossChainTx + } + 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 ErrInvalidLengthCrossChainTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthCrossChainTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.GasPriorityFee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipCrossChainTx(dAtA[iNdEx:]) diff --git a/x/crosschain/types/errors.go b/x/crosschain/types/errors.go index b468d2c962..279442d2c7 100644 --- a/x/crosschain/types/errors.go +++ b/x/crosschain/types/errors.go @@ -56,4 +56,5 @@ var ( "migration tx from an old tss address detected", ) ErrValidatingInbound = errorsmod.Register(ModuleName, 1157, "unable to validate inbound") + ErrInvalidGasLimit = errorsmod.Register(ModuleName, 1158, "invalid gas limit") ) diff --git a/x/crosschain/types/gas_price.pb.go b/x/crosschain/types/gas_price.pb.go index 5c675158f0..d5ccffd28e 100644 --- a/x/crosschain/types/gas_price.pb.go +++ b/x/crosschain/types/gas_price.pb.go @@ -23,13 +23,16 @@ var _ = math.Inf const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type GasPrice struct { - Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` - Index string `protobuf:"bytes,2,opt,name=index,proto3" json:"index,omitempty"` - ChainId int64 `protobuf:"varint,3,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - Signers []string `protobuf:"bytes,4,rep,name=signers,proto3" json:"signers,omitempty"` - BlockNums []uint64 `protobuf:"varint,5,rep,packed,name=block_nums,json=blockNums,proto3" json:"block_nums,omitempty"` - Prices []uint64 `protobuf:"varint,6,rep,packed,name=prices,proto3" json:"prices,omitempty"` - MedianIndex uint64 `protobuf:"varint,7,opt,name=median_index,json=medianIndex,proto3" json:"median_index,omitempty"` + Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` + Index string `protobuf:"bytes,2,opt,name=index,proto3" json:"index,omitempty"` + ChainId int64 `protobuf:"varint,3,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + Signers []string `protobuf:"bytes,4,rep,name=signers,proto3" json:"signers,omitempty"` + BlockNums []uint64 `protobuf:"varint,5,rep,packed,name=block_nums,json=blockNums,proto3" json:"block_nums,omitempty"` + Prices []uint64 `protobuf:"varint,6,rep,packed,name=prices,proto3" json:"prices,omitempty"` + // index of the median gas price in the prices array + MedianIndex uint64 `protobuf:"varint,7,opt,name=median_index,json=medianIndex,proto3" json:"median_index,omitempty"` + // priority fees for EIP-1559 + PriorityFees []uint64 `protobuf:"varint,8,rep,packed,name=priority_fees,json=priorityFees,proto3" json:"priority_fees,omitempty"` } func (m *GasPrice) Reset() { *m = GasPrice{} } @@ -114,6 +117,13 @@ func (m *GasPrice) GetMedianIndex() uint64 { return 0 } +func (m *GasPrice) GetPriorityFees() []uint64 { + if m != nil { + return m.PriorityFees + } + return nil +} + func init() { proto.RegisterType((*GasPrice)(nil), "zetachain.zetacore.crosschain.GasPrice") } @@ -123,25 +133,26 @@ func init() { } var fileDescriptor_6c44a94bd00549c5 = []byte{ - // 277 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x90, 0xc1, 0x4a, 0xc3, 0x30, - 0x1c, 0xc6, 0x17, 0xdb, 0xb5, 0x5b, 0xf4, 0x14, 0x44, 0xe2, 0x61, 0xa1, 0x7a, 0xea, 0x65, 0x1d, - 0xe2, 0x1b, 0x78, 0x91, 0x21, 0x88, 0xf4, 0xe8, 0xa5, 0xa4, 0x69, 0xe8, 0x82, 0xb6, 0x29, 0xf9, - 0xa7, 0x30, 0x7d, 0x0a, 0x1f, 0x4b, 0x6f, 0x3b, 0x7a, 0x94, 0xf6, 0x45, 0xa4, 0xe9, 0xa6, 0xe2, - 0xad, 0xbf, 0x5f, 0xbf, 0x7c, 0xfc, 0xf9, 0xf0, 0xf2, 0x55, 0x5a, 0x2e, 0x36, 0x5c, 0xd5, 0x2b, - 0xf7, 0xa5, 0x8d, 0x5c, 0x09, 0xa3, 0x01, 0x46, 0x57, 0x72, 0xc8, 0x1a, 0xa3, 0x84, 0x4c, 0x1a, - 0xa3, 0xad, 0x26, 0x8b, 0x9f, 0x78, 0x72, 0x88, 0x27, 0xbf, 0xf1, 0xcb, 0x0f, 0x84, 0x67, 0xb7, - 0x1c, 0x1e, 0x86, 0x17, 0x84, 0xe2, 0x50, 0x18, 0xc9, 0xad, 0x36, 0x14, 0x45, 0x28, 0x9e, 0xa7, - 0x07, 0x24, 0xa7, 0x78, 0xaa, 0xea, 0x42, 0x6e, 0xe9, 0x91, 0xf3, 0x23, 0x90, 0x73, 0x3c, 0x73, - 0x2d, 0x99, 0x2a, 0xa8, 0x17, 0xa1, 0xd8, 0x4b, 0x43, 0xc7, 0xeb, 0x62, 0xa8, 0x02, 0x55, 0xd6, - 0xd2, 0x00, 0xf5, 0x23, 0x6f, 0xa8, 0xda, 0x23, 0x59, 0x60, 0x9c, 0x3f, 0x6b, 0xf1, 0x94, 0xd5, - 0x6d, 0x05, 0x74, 0x1a, 0x79, 0xb1, 0x9f, 0xce, 0x9d, 0xb9, 0x6f, 0x2b, 0x20, 0x67, 0x38, 0x70, - 0xe7, 0x03, 0x0d, 0xdc, 0xaf, 0x3d, 0x91, 0x0b, 0x7c, 0x52, 0xc9, 0x42, 0xf1, 0x3a, 0x1b, 0x0f, - 0x09, 0x23, 0x14, 0xfb, 0xe9, 0xf1, 0xe8, 0xd6, 0x83, 0xba, 0xb9, 0x7b, 0xef, 0x18, 0xda, 0x75, - 0x0c, 0x7d, 0x75, 0x0c, 0xbd, 0xf5, 0x6c, 0xb2, 0xeb, 0xd9, 0xe4, 0xb3, 0x67, 0x93, 0xc7, 0xab, - 0x52, 0xd9, 0x4d, 0x9b, 0x27, 0x42, 0x57, 0x6e, 0xb4, 0xe5, 0xbf, 0xfd, 0xb6, 0x7f, 0x17, 0xb4, - 0x2f, 0x8d, 0x84, 0x3c, 0x70, 0xf3, 0x5d, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, 0xdd, 0xca, 0xb1, - 0x6a, 0x6f, 0x01, 0x00, 0x00, + // 300 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x90, 0xbf, 0x4e, 0xc3, 0x30, + 0x18, 0xc4, 0x6b, 0xd2, 0xbf, 0xa6, 0x2c, 0x16, 0x42, 0x66, 0xa8, 0x15, 0x60, 0xc9, 0xd2, 0x54, + 0x88, 0x37, 0x60, 0x00, 0x55, 0x48, 0x08, 0x65, 0x64, 0x89, 0x5c, 0xe7, 0xa3, 0xb5, 0x20, 0x71, + 0xe4, 0xcf, 0x95, 0x5a, 0x9e, 0x82, 0xc7, 0x62, 0xec, 0xc8, 0x88, 0xda, 0x9d, 0x67, 0x40, 0x71, + 0x1a, 0x40, 0x6c, 0xbe, 0x9f, 0xef, 0x3b, 0x9d, 0x8e, 0x8e, 0x5f, 0xc1, 0x49, 0xb5, 0x90, 0xba, + 0x98, 0xf8, 0x97, 0xb1, 0x30, 0x51, 0xd6, 0x20, 0xd6, 0x6c, 0x2e, 0x31, 0x2d, 0xad, 0x56, 0x10, + 0x97, 0xd6, 0x38, 0xc3, 0x46, 0x3f, 0xf6, 0xb8, 0xb1, 0xc7, 0xbf, 0xf6, 0xf3, 0x2f, 0x42, 0xfb, + 0xb7, 0x12, 0x1f, 0xaa, 0x0b, 0xc6, 0x69, 0x4f, 0x59, 0x90, 0xce, 0x58, 0x4e, 0x42, 0x12, 0x0d, + 0x92, 0x46, 0xb2, 0x63, 0xda, 0xd1, 0x45, 0x06, 0x2b, 0x7e, 0xe0, 0x79, 0x2d, 0xd8, 0x29, 0xed, + 0xfb, 0x94, 0x54, 0x67, 0x3c, 0x08, 0x49, 0x14, 0x24, 0x3d, 0xaf, 0xa7, 0x59, 0x15, 0x85, 0x7a, + 0x5e, 0x80, 0x45, 0xde, 0x0e, 0x83, 0x2a, 0x6a, 0x2f, 0xd9, 0x88, 0xd2, 0xd9, 0x8b, 0x51, 0xcf, + 0x69, 0xb1, 0xcc, 0x91, 0x77, 0xc2, 0x20, 0x6a, 0x27, 0x03, 0x4f, 0xee, 0x97, 0x39, 0xb2, 0x13, + 0xda, 0xf5, 0xf5, 0x91, 0x77, 0xfd, 0xd7, 0x5e, 0xb1, 0x33, 0x3a, 0xcc, 0x21, 0xd3, 0xb2, 0x48, + 0xeb, 0x22, 0xbd, 0x90, 0x44, 0xed, 0xe4, 0xb0, 0x66, 0x53, 0x5f, 0xe7, 0x82, 0x1e, 0x95, 0x56, + 0x1b, 0xab, 0xdd, 0x3a, 0x7d, 0x02, 0x40, 0xde, 0xf7, 0x09, 0xc3, 0x06, 0xde, 0x00, 0xe0, 0xf5, + 0xdd, 0xfb, 0x56, 0x90, 0xcd, 0x56, 0x90, 0xcf, 0xad, 0x20, 0x6f, 0x3b, 0xd1, 0xda, 0xec, 0x44, + 0xeb, 0x63, 0x27, 0x5a, 0x8f, 0x97, 0x73, 0xed, 0x16, 0xcb, 0x59, 0xac, 0x4c, 0xee, 0x97, 0x1d, + 0xff, 0x1b, 0x79, 0xf5, 0x77, 0x66, 0xb7, 0x2e, 0x01, 0x67, 0x5d, 0xbf, 0xf1, 0xd5, 0x77, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x4e, 0x6a, 0xcb, 0x1e, 0x94, 0x01, 0x00, 0x00, } func (m *GasPrice) Marshal() (dAtA []byte, err error) { @@ -164,15 +175,10 @@ func (m *GasPrice) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.MedianIndex != 0 { - i = encodeVarintGasPrice(dAtA, i, uint64(m.MedianIndex)) - i-- - dAtA[i] = 0x38 - } - if len(m.Prices) > 0 { - dAtA2 := make([]byte, len(m.Prices)*10) + if len(m.PriorityFees) > 0 { + dAtA2 := make([]byte, len(m.PriorityFees)*10) var j1 int - for _, num := range m.Prices { + for _, num := range m.PriorityFees { for num >= 1<<7 { dAtA2[j1] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 @@ -185,12 +191,17 @@ func (m *GasPrice) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], dAtA2[:j1]) i = encodeVarintGasPrice(dAtA, i, uint64(j1)) i-- - dAtA[i] = 0x32 + dAtA[i] = 0x42 } - if len(m.BlockNums) > 0 { - dAtA4 := make([]byte, len(m.BlockNums)*10) + if m.MedianIndex != 0 { + i = encodeVarintGasPrice(dAtA, i, uint64(m.MedianIndex)) + i-- + dAtA[i] = 0x38 + } + if len(m.Prices) > 0 { + dAtA4 := make([]byte, len(m.Prices)*10) var j3 int - for _, num := range m.BlockNums { + for _, num := range m.Prices { for num >= 1<<7 { dAtA4[j3] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 @@ -203,6 +214,24 @@ func (m *GasPrice) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], dAtA4[:j3]) i = encodeVarintGasPrice(dAtA, i, uint64(j3)) i-- + dAtA[i] = 0x32 + } + if len(m.BlockNums) > 0 { + dAtA6 := make([]byte, len(m.BlockNums)*10) + var j5 int + for _, num := range m.BlockNums { + for num >= 1<<7 { + dAtA6[j5] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j5++ + } + dAtA6[j5] = uint8(num) + j5++ + } + i -= j5 + copy(dAtA[i:], dAtA6[:j5]) + i = encodeVarintGasPrice(dAtA, i, uint64(j5)) + i-- dAtA[i] = 0x2a } if len(m.Signers) > 0 { @@ -287,6 +316,13 @@ func (m *GasPrice) Size() (n int) { if m.MedianIndex != 0 { n += 1 + sovGasPrice(uint64(m.MedianIndex)) } + if len(m.PriorityFees) > 0 { + l = 0 + for _, e := range m.PriorityFees { + l += sovGasPrice(uint64(e)) + } + n += 1 + sovGasPrice(uint64(l)) + l + } return n } @@ -611,6 +647,82 @@ func (m *GasPrice) Unmarshal(dAtA []byte) error { break } } + case 8: + if wireType == 0 { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGasPrice + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.PriorityFees = append(m.PriorityFees, v) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGasPrice + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return ErrInvalidLengthGasPrice + } + postIndex := iNdEx + packedLen + if postIndex < 0 { + return ErrInvalidLengthGasPrice + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var elementCount int + var count int + for _, integer := range dAtA[iNdEx:postIndex] { + if integer < 128 { + count++ + } + } + elementCount = count + if elementCount != 0 && len(m.PriorityFees) == 0 { + m.PriorityFees = make([]uint64, 0, elementCount) + } + for iNdEx < postIndex { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGasPrice + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.PriorityFees = append(m.PriorityFees, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field PriorityFees", wireType) + } default: iNdEx = preIndex skippy, err := skipGasPrice(dAtA[iNdEx:]) diff --git a/x/crosschain/types/keys.go b/x/crosschain/types/keys.go index 5bb89a61ea..8496ccf608 100644 --- a/x/crosschain/types/keys.go +++ b/x/crosschain/types/keys.go @@ -25,7 +25,8 @@ const ( ProtocolFee = 2000000000000000000 - //TssMigrationGasMultiplierEVM is multiplied to the median gas price to get the gas price for the tss migration . This is done to avoid the tss migration tx getting stuck in the mempool + // TssMigrationGasMultiplierEVM is multiplied to the median gas price to get the gas price for the tss migration . + // This is done to avoid the tss migration tx getting stuck in the mempool TssMigrationGasMultiplierEVM = "2.5" // TSSMigrationBufferAmountEVM is the buffer amount added to the gas price for the tss migration transaction TSSMigrationBufferAmountEVM = "2100000000" diff --git a/x/crosschain/types/message_vote_gas_price.go b/x/crosschain/types/message_vote_gas_price.go index d1d3dceb7a..fd84a77c02 100644 --- a/x/crosschain/types/message_vote_gas_price.go +++ b/x/crosschain/types/message_vote_gas_price.go @@ -10,13 +10,17 @@ import ( var _ sdk.Msg = &MsgVoteGasPrice{} -func NewMsgVoteGasPrice(creator string, chain int64, price uint64, supply string, blockNumber uint64) *MsgVoteGasPrice { +// NewMsgVoteGasPrice creates a new MsgVoteGasPrice instance. +// Notes: +// - Price is in `wei` for EVM and `satoshi per byte` for UTXO. +// - PriorityFeePrice is only for EVM that supports EIP-1559 ("London" hard fork). +func NewMsgVoteGasPrice(creator string, chain int64, price, priorityFee, blockNumber uint64) *MsgVoteGasPrice { return &MsgVoteGasPrice{ Creator: creator, ChainId: chain, Price: price, + PriorityFee: priorityFee, BlockNumber: blockNumber, - Supply: supply, } } diff --git a/x/crosschain/types/message_vote_gas_price_test.go b/x/crosschain/types/message_vote_gas_price_test.go index 936d694417..91a450c79c 100644 --- a/x/crosschain/types/message_vote_gas_price_test.go +++ b/x/crosschain/types/message_vote_gas_price_test.go @@ -24,7 +24,7 @@ func TestMsgVoteGasPrice_ValidateBasic(t *testing.T) { "invalid", 1, 1, - "1000", + 0, 1, ), err: sdkerrors.ErrInvalidAddress, @@ -35,7 +35,7 @@ func TestMsgVoteGasPrice_ValidateBasic(t *testing.T) { sample.AccAddress(), -1, 1, - "1000", + 0, 1, ), err: sdkerrors.ErrInvalidChainID, @@ -46,7 +46,7 @@ func TestMsgVoteGasPrice_ValidateBasic(t *testing.T) { sample.AccAddress(), 1, 1, - "1000", + 0, 1, ), }, diff --git a/x/crosschain/types/outbound_params.go b/x/crosschain/types/outbound_params.go index 361462a1b4..2d4a259a3a 100644 --- a/x/crosschain/types/outbound_params.go +++ b/x/crosschain/types/outbound_params.go @@ -3,6 +3,8 @@ package types import ( "fmt" "strconv" + + "github.com/pkg/errors" ) func (m OutboundParams) GetGasPriceUInt64() (uint64, error) { @@ -14,6 +16,20 @@ func (m OutboundParams) GetGasPriceUInt64() (uint64, error) { return gasPrice, nil } +func (m OutboundParams) GetGasPriorityFeeUInt64() (uint64, error) { + // noop + if m.GasPriorityFee == "" { + return 0, nil + } + + fee, err := strconv.ParseUint(m.GasPriorityFee, 10, 64) + if err != nil { + return 0, errors.Wrapf(err, "unable to parse priority fee from %q", m.GasPriorityFee) + } + + return fee, nil +} + func (m OutboundParams) Validate() error { if m.Receiver == "" { return fmt.Errorf("receiver cannot be empty") diff --git a/x/crosschain/types/tx.pb.go b/x/crosschain/types/tx.pb.go index 0439d79e85..4bd154f595 100644 --- a/x/crosschain/types/tx.pb.go +++ b/x/crosschain/types/tx.pb.go @@ -717,8 +717,8 @@ type MsgVoteGasPrice struct { Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` ChainId int64 `protobuf:"varint,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` Price uint64 `protobuf:"varint,3,opt,name=price,proto3" json:"price,omitempty"` + PriorityFee uint64 `protobuf:"varint,6,opt,name=priority_fee,json=priorityFee,proto3" json:"priority_fee,omitempty"` BlockNumber uint64 `protobuf:"varint,4,opt,name=block_number,json=blockNumber,proto3" json:"block_number,omitempty"` - Supply string `protobuf:"bytes,5,opt,name=supply,proto3" json:"supply,omitempty"` } func (m *MsgVoteGasPrice) Reset() { *m = MsgVoteGasPrice{} } @@ -775,18 +775,18 @@ func (m *MsgVoteGasPrice) GetPrice() uint64 { return 0 } -func (m *MsgVoteGasPrice) GetBlockNumber() uint64 { +func (m *MsgVoteGasPrice) GetPriorityFee() uint64 { if m != nil { - return m.BlockNumber + return m.PriorityFee } return 0 } -func (m *MsgVoteGasPrice) GetSupply() string { +func (m *MsgVoteGasPrice) GetBlockNumber() uint64 { if m != nil { - return m.Supply + return m.BlockNumber } - return "" + return 0 } type MsgVoteGasPriceResponse struct { @@ -1463,104 +1463,105 @@ func init() { } var fileDescriptor_15f0860550897740 = []byte{ - // 1546 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x58, 0xdd, 0x6e, 0x1b, 0xd5, - 0x13, 0xcf, 0x36, 0x89, 0x63, 0x8f, 0xf3, 0xd1, 0xee, 0x3f, 0x4d, 0x9d, 0x4d, 0xe3, 0xa4, 0xee, - 0xbf, 0x21, 0x42, 0xad, 0x9d, 0xba, 0xa5, 0x94, 0x16, 0x01, 0x8d, 0xe9, 0x47, 0x44, 0xdd, 0x46, - 0xdb, 0x14, 0x10, 0x37, 0xab, 0xf5, 0xee, 0xc9, 0x7a, 0x65, 0x7b, 0xd7, 0xda, 0x73, 0x6c, 0x39, - 0x15, 0x12, 0x08, 0x09, 0x89, 0x4b, 0x40, 0x48, 0x48, 0x5c, 0x70, 0xc7, 0x0b, 0xf0, 0x14, 0xbd, - 0xac, 0xb8, 0x42, 0x5c, 0x54, 0xa8, 0x7d, 0x02, 0x78, 0x02, 0xb4, 0x73, 0xce, 0x6e, 0xbd, 0xeb, - 0xcf, 0xb8, 0x42, 0xdc, 0xd8, 0x3b, 0x73, 0xe6, 0x37, 0x67, 0x66, 0xce, 0xcc, 0x99, 0xd9, 0x85, - 0xad, 0x27, 0x84, 0xe9, 0x46, 0x55, 0xb7, 0x9d, 0x02, 0x3e, 0xb9, 0x1e, 0x29, 0x18, 0x9e, 0x4b, - 0x29, 0xe7, 0xb1, 0x4e, 0xbe, 0xe9, 0xb9, 0xcc, 0x95, 0xd7, 0x43, 0xb9, 0x7c, 0x20, 0x97, 0x7f, - 0x25, 0xa7, 0x2c, 0x5b, 0xae, 0xe5, 0xa2, 0x64, 0xc1, 0x7f, 0xe2, 0x20, 0xe5, 0xcd, 0x3e, 0xca, - 0x9b, 0x35, 0xab, 0x80, 0x2c, 0x2a, 0xfe, 0x84, 0xec, 0xd6, 0x20, 0x59, 0xd7, 0x76, 0xf0, 0x67, - 0x84, 0xce, 0xa6, 0xe7, 0xba, 0x87, 0x54, 0xfc, 0x09, 0xd9, 0x6b, 0xc3, 0x9d, 0xf3, 0x74, 0x46, - 0xb4, 0xba, 0xdd, 0xb0, 0x19, 0xf1, 0xb4, 0xc3, 0xba, 0x6e, 0x09, 0x5c, 0xee, 0x7b, 0x09, 0xe4, - 0x32, 0xb5, 0xca, 0xb6, 0xe5, 0x8b, 0x1c, 0x50, 0x7a, 0xa7, 0xe5, 0x98, 0x54, 0xce, 0xc0, 0x9c, - 0xe1, 0x11, 0x9d, 0xb9, 0x5e, 0x46, 0xda, 0x94, 0xb6, 0x53, 0x6a, 0x40, 0xca, 0xab, 0x90, 0x44, - 0x95, 0x9a, 0x6d, 0x66, 0x4e, 0x6c, 0x4a, 0xdb, 0xd3, 0xea, 0x1c, 0xd2, 0x7b, 0xa6, 0x7c, 0x17, - 0x12, 0x7a, 0xc3, 0x6d, 0x39, 0x2c, 0x33, 0xed, 0x63, 0x76, 0x0b, 0x4f, 0x9f, 0x6f, 0x4c, 0xfd, - 0xf1, 0x7c, 0xe3, 0x0d, 0xcb, 0x66, 0xd5, 0x56, 0x25, 0x6f, 0xb8, 0x8d, 0x82, 0xe1, 0xd2, 0x86, - 0x4b, 0xc5, 0xdf, 0x25, 0x6a, 0xd6, 0x0a, 0xec, 0xa8, 0x49, 0x68, 0xfe, 0xb1, 0xed, 0x30, 0x55, - 0xc0, 0x73, 0x67, 0x41, 0xe9, 0xb5, 0x49, 0x25, 0xb4, 0xe9, 0x3a, 0x94, 0xe4, 0x1e, 0xc0, 0xff, - 0xca, 0xd4, 0x7a, 0xdc, 0x34, 0xf9, 0xe2, 0x2d, 0xd3, 0xf4, 0x08, 0x1d, 0x66, 0xf2, 0x3a, 0x00, - 0xa3, 0x54, 0x6b, 0xb6, 0x2a, 0x35, 0x72, 0x84, 0x46, 0xa7, 0xd4, 0x14, 0xa3, 0x74, 0x1f, 0x19, - 0xb9, 0x75, 0x58, 0xeb, 0xa3, 0x2f, 0xdc, 0xee, 0xe7, 0x13, 0xb0, 0x5c, 0xa6, 0xd6, 0x2d, 0xd3, - 0xdc, 0x73, 0x2a, 0x6e, 0xcb, 0x31, 0x0f, 0x3c, 0xdd, 0xa8, 0x11, 0x6f, 0xb2, 0x18, 0x9d, 0x81, - 0x39, 0xd6, 0xd1, 0xaa, 0x3a, 0xad, 0xf2, 0x20, 0xa9, 0x09, 0xd6, 0xb9, 0xa7, 0xd3, 0xaa, 0xbc, - 0x0b, 0x29, 0xff, 0xe8, 0x35, 0x3f, 0x1c, 0x99, 0x99, 0x4d, 0x69, 0x7b, 0xb1, 0x78, 0x21, 0xdf, - 0x27, 0x13, 0x9b, 0x35, 0x2b, 0x8f, 0x39, 0x52, 0x72, 0x6d, 0xe7, 0xe0, 0xa8, 0x49, 0xd4, 0xa4, - 0x21, 0x9e, 0xe4, 0x1b, 0x30, 0x8b, 0x49, 0x91, 0x99, 0xdd, 0x94, 0xb6, 0xd3, 0xc5, 0xff, 0x0f, - 0xc2, 0x8b, 0xcc, 0xd9, 0xf7, 0xff, 0x54, 0x0e, 0xf1, 0x83, 0x54, 0xa9, 0xbb, 0x46, 0x8d, 0xdb, - 0x96, 0xe0, 0x41, 0x42, 0x0e, 0x9a, 0xb7, 0x0a, 0x49, 0xd6, 0xd1, 0x6c, 0xc7, 0x24, 0x9d, 0xcc, - 0x1c, 0x77, 0x89, 0x75, 0xf6, 0x7c, 0x32, 0x97, 0x85, 0xb3, 0xfd, 0xe2, 0x13, 0x06, 0xf0, 0x37, - 0x09, 0x4e, 0x95, 0xa9, 0xf5, 0x49, 0xd5, 0x66, 0xa4, 0x6e, 0x53, 0x76, 0x5b, 0x2d, 0x15, 0x77, - 0x86, 0x44, 0xef, 0x3c, 0x2c, 0x10, 0xcf, 0x28, 0xee, 0x68, 0x3a, 0x3f, 0x09, 0x71, 0x62, 0xf3, - 0xc8, 0x0c, 0x4e, 0xbb, 0x3b, 0xc4, 0xd3, 0xd1, 0x10, 0xcb, 0x30, 0xe3, 0xe8, 0x0d, 0x1e, 0xc4, - 0x94, 0x8a, 0xcf, 0xf2, 0x0a, 0x24, 0xe8, 0x51, 0xa3, 0xe2, 0xd6, 0x31, 0x34, 0x29, 0x55, 0x50, - 0xb2, 0x02, 0x49, 0x93, 0x18, 0x76, 0x43, 0xaf, 0x53, 0xf4, 0x79, 0x41, 0x0d, 0x69, 0x79, 0x0d, - 0x52, 0x96, 0x4e, 0x79, 0xd5, 0x08, 0x9f, 0x93, 0x96, 0x4e, 0xef, 0xfb, 0x74, 0x4e, 0x83, 0xd5, - 0x1e, 0x9f, 0x02, 0x8f, 0x7d, 0x0f, 0x9e, 0x44, 0x3c, 0xe0, 0x1e, 0xce, 0x3f, 0xe9, 0xf6, 0x60, - 0x1d, 0xc0, 0x30, 0xc2, 0x98, 0x8a, 0xac, 0xf4, 0x39, 0x3c, 0xaa, 0x7f, 0x49, 0x70, 0x9a, 0x87, - 0xf5, 0x61, 0x8b, 0xbd, 0x7e, 0xde, 0x2d, 0xc3, 0xac, 0xe3, 0x3a, 0x06, 0xc1, 0x60, 0xcd, 0xa8, - 0x9c, 0xe8, 0xce, 0xc6, 0x99, 0x48, 0x36, 0xfe, 0x37, 0x99, 0xf4, 0x1e, 0xac, 0xf7, 0x75, 0x39, - 0x0c, 0xec, 0x3a, 0x80, 0x4d, 0x35, 0x8f, 0x34, 0xdc, 0x36, 0x31, 0xd1, 0xfb, 0xa4, 0x9a, 0xb2, - 0xa9, 0xca, 0x19, 0x39, 0x02, 0x99, 0x32, 0xb5, 0x38, 0xf5, 0xef, 0x45, 0x2d, 0x97, 0x83, 0xcd, - 0x41, 0xdb, 0x84, 0x49, 0xff, 0xa3, 0x04, 0x4b, 0x65, 0x6a, 0x7d, 0xec, 0x32, 0x72, 0x57, 0xa7, - 0xfb, 0x9e, 0x6d, 0x90, 0x89, 0x4d, 0x68, 0xfa, 0xe8, 0xc0, 0x04, 0x24, 0xe4, 0x73, 0x30, 0xcf, - 0x63, 0xec, 0xb4, 0x1a, 0x15, 0xe2, 0xe1, 0xe9, 0xcd, 0xa8, 0x69, 0xe4, 0x3d, 0x40, 0x16, 0xa6, - 0x7c, 0xab, 0xd9, 0xac, 0x1f, 0x85, 0x29, 0x8f, 0x54, 0x6e, 0x15, 0xce, 0xc4, 0x0c, 0x0b, 0x8d, - 0xfe, 0x25, 0x11, 0x1a, 0x1d, 0xf8, 0x35, 0xc4, 0xe8, 0x35, 0xc0, 0x74, 0xe5, 0xc7, 0xcc, 0xf3, - 0x37, 0xe9, 0x33, 0xf0, 0x94, 0xaf, 0xc2, 0x8a, 0x5b, 0xa1, 0xc4, 0x6b, 0x13, 0x53, 0x73, 0x85, - 0xae, 0xee, 0x6b, 0x6f, 0x39, 0x58, 0x0d, 0x36, 0x42, 0x54, 0x09, 0xb2, 0xbd, 0x28, 0x91, 0x4c, - 0xc4, 0xb6, 0xaa, 0x4c, 0x38, 0xba, 0x16, 0x47, 0xef, 0x62, 0x7a, 0xa1, 0x88, 0x7c, 0x13, 0x94, - 0x5e, 0x25, 0x7e, 0x25, 0xb7, 0x28, 0x31, 0x33, 0x80, 0x0a, 0xce, 0xc4, 0x15, 0xdc, 0xd5, 0xe9, - 0x63, 0x4a, 0x4c, 0xf9, 0x4b, 0x09, 0x2e, 0xf4, 0xa2, 0xc9, 0xe1, 0x21, 0x31, 0x98, 0xdd, 0x26, - 0xa8, 0x87, 0x9f, 0x47, 0x1a, 0x7b, 0x5c, 0x5e, 0xf4, 0xb8, 0xad, 0x31, 0x7a, 0xdc, 0x9e, 0xc3, - 0xd4, 0x73, 0xf1, 0x8d, 0x6f, 0x07, 0xaa, 0xc3, 0x34, 0xd9, 0x1f, 0x6d, 0x01, 0xbf, 0x93, 0xe6, - 0xd1, 0x95, 0xa1, 0x1a, 0xf1, 0xb2, 0x92, 0x5d, 0x58, 0x6c, 0xeb, 0xf5, 0x16, 0xd1, 0x3c, 0x62, - 0x10, 0xdb, 0x2f, 0x1d, 0x4c, 0x89, 0xdd, 0x7b, 0xc7, 0x6c, 0xd0, 0x7f, 0x3f, 0xdf, 0x38, 0x7d, - 0xa4, 0x37, 0xea, 0x37, 0x72, 0x51, 0x75, 0x39, 0x75, 0x01, 0x19, 0xaa, 0xa0, 0xe5, 0x0f, 0x21, - 0x41, 0x99, 0xce, 0x5a, 0xfc, 0x52, 0x5d, 0x2c, 0x5e, 0x1c, 0xd8, 0xc9, 0xf8, 0x5c, 0x24, 0x80, - 0x8f, 0x10, 0xa3, 0x0a, 0xac, 0x7c, 0x01, 0x16, 0x43, 0xff, 0x51, 0x50, 0xdc, 0x17, 0x0b, 0x01, - 0xb7, 0xe4, 0x33, 0xe5, 0x8b, 0x20, 0x87, 0x62, 0x7e, 0x9f, 0xe7, 0x15, 0x9b, 0xc4, 0xe0, 0x9c, - 0x0c, 0x56, 0x0e, 0x28, 0x7d, 0x80, 0x57, 0x5e, 0xa4, 0xcf, 0xa6, 0x26, 0xea, 0xb3, 0x5d, 0x25, - 0x14, 0xc4, 0x3c, 0x2c, 0xa1, 0x9f, 0x66, 0x60, 0x51, 0xac, 0x89, 0x76, 0x38, 0xa4, 0x82, 0xfc, - 0x12, 0x25, 0x8e, 0x49, 0x3c, 0x51, 0x3e, 0x82, 0x92, 0xb7, 0x60, 0x89, 0x3f, 0x69, 0xb1, 0x1e, - 0xb7, 0xc0, 0xd9, 0x25, 0x71, 0x37, 0x28, 0x90, 0x14, 0x47, 0xe0, 0x89, 0xfb, 0x3b, 0xa4, 0xfd, - 0xe0, 0x05, 0xcf, 0x22, 0x78, 0xb3, 0x5c, 0x45, 0xc0, 0xe5, 0xc1, 0x7b, 0x35, 0xb3, 0x25, 0x5e, - 0x6b, 0x66, 0xf3, 0xbd, 0x6c, 0x10, 0x4a, 0x75, 0x8b, 0x87, 0x3e, 0xa5, 0x06, 0xa4, 0x7f, 0x57, - 0xd9, 0x4e, 0xd7, 0x05, 0x90, 0xc2, 0xe5, 0xb4, 0xe0, 0x61, 0xdd, 0xef, 0xc0, 0x72, 0x20, 0x12, - 0xa9, 0x76, 0x5e, 0xac, 0xb2, 0x58, 0xeb, 0x2e, 0xf2, 0x48, 0x73, 0x4e, 0xa3, 0x58, 0xd8, 0x9c, - 0xa3, 0x67, 0x3c, 0x3f, 0xd9, 0x2c, 0xb5, 0x06, 0x29, 0xd6, 0xd1, 0x5c, 0xcf, 0xb6, 0x6c, 0x27, - 0xb3, 0xc0, 0x83, 0xcb, 0x3a, 0x0f, 0x91, 0xf6, 0x2f, 0x65, 0x9d, 0x52, 0xc2, 0x32, 0x8b, 0xb8, - 0xc0, 0x09, 0x79, 0x03, 0xd2, 0xa4, 0x4d, 0x1c, 0x26, 0x9a, 0xdb, 0x12, 0x5a, 0x05, 0xc8, 0xe2, - 0xfd, 0x2d, 0x03, 0x2b, 0xd1, 0xdc, 0x08, 0xd3, 0xe6, 0x3e, 0x8e, 0x48, 0xb7, 0x2a, 0xae, 0xc7, - 0x1e, 0xb1, 0x96, 0x51, 0x2b, 0x95, 0x0e, 0x3e, 0x1d, 0x3e, 0xd1, 0x0e, 0x9b, 0x1d, 0xd6, 0x70, - 0x38, 0x89, 0x6a, 0x0b, 0xb7, 0x6a, 0xe3, 0x38, 0xab, 0x92, 0xc3, 0x96, 0x63, 0xa2, 0x08, 0x31, - 0x5f, 0x6b, 0x37, 0x9e, 0x69, 0xbe, 0xb6, 0x70, 0xdc, 0xe1, 0x57, 0xfc, 0x02, 0xe7, 0x8a, 0x79, - 0x47, 0x8c, 0x89, 0x3d, 0xfb, 0xbe, 0xaa, 0x1c, 0x09, 0xad, 0xe6, 0x73, 0xb8, 0xaa, 0x33, 0x72, - 0x9f, 0xbf, 0xae, 0xdc, 0xf1, 0xdf, 0x56, 0x86, 0x58, 0x67, 0x80, 0xdc, 0xfb, 0x76, 0x83, 0x56, - 0xa6, 0x8b, 0x85, 0xfc, 0xd0, 0x77, 0xb9, 0x7c, 0x7c, 0x9b, 0xdd, 0x19, 0x3f, 0xfd, 0xd5, 0x93, - 0x5e, 0x8c, 0x9f, 0x3b, 0x0f, 0xe7, 0x06, 0xda, 0x16, 0x78, 0x50, 0xfc, 0x75, 0x1e, 0xa6, 0xcb, - 0xd4, 0x92, 0xbf, 0x91, 0x40, 0xee, 0x33, 0xb7, 0x5d, 0x1d, 0x61, 0x4c, 0xdf, 0xd1, 0x47, 0x79, - 0x77, 0x12, 0x54, 0x38, 0x30, 0x7d, 0x2d, 0xc1, 0xa9, 0xde, 0x37, 0x97, 0x2b, 0x63, 0xe9, 0x8c, - 0x82, 0x94, 0x9b, 0x13, 0x80, 0x42, 0x3b, 0xbe, 0x93, 0xe0, 0x74, 0xff, 0xb9, 0xec, 0xed, 0xd1, - 0x6a, 0xfb, 0x02, 0x95, 0xf7, 0x27, 0x04, 0x86, 0x36, 0xb5, 0x61, 0x3e, 0x32, 0x9e, 0xe5, 0x47, - 0x2b, 0xec, 0x96, 0x57, 0xae, 0x1d, 0x4f, 0x3e, 0xbe, 0x6f, 0x38, 0x61, 0x8d, 0xb9, 0x6f, 0x20, - 0x3f, 0xee, 0xbe, 0xf1, 0xd6, 0x24, 0x53, 0x48, 0x77, 0xb7, 0xa5, 0x4b, 0xe3, 0xa9, 0x11, 0xe2, - 0xca, 0x5b, 0xc7, 0x12, 0x0f, 0x37, 0xfd, 0x1c, 0x16, 0x63, 0x2f, 0x7e, 0x3b, 0xa3, 0x15, 0x45, - 0x11, 0xca, 0xf5, 0xe3, 0x22, 0xc2, 0xdd, 0xbf, 0x92, 0xe0, 0x64, 0xcf, 0x87, 0x82, 0xe2, 0x68, - 0x75, 0x71, 0x8c, 0x72, 0xe3, 0xf8, 0x98, 0xd0, 0x88, 0x2f, 0x60, 0x29, 0xfe, 0x79, 0xe5, 0xf2, - 0x68, 0x75, 0x31, 0x88, 0xf2, 0xce, 0xb1, 0x21, 0xdd, 0x67, 0x10, 0xeb, 0x2c, 0x63, 0x9c, 0x41, - 0x14, 0x31, 0xce, 0x19, 0xf4, 0xef, 0x37, 0x78, 0x05, 0xf5, 0x76, 0x9b, 0x2b, 0xe3, 0x54, 0x6f, - 0x0c, 0x34, 0xce, 0x15, 0x34, 0xb0, 0xbf, 0xc8, 0x3f, 0x48, 0xb0, 0x32, 0xa0, 0xb9, 0x5c, 0x1f, - 0xf7, 0x74, 0xe3, 0x48, 0xe5, 0x83, 0x49, 0x91, 0x81, 0x59, 0xbb, 0x1f, 0x3d, 0x7d, 0x91, 0x95, - 0x9e, 0xbd, 0xc8, 0x4a, 0x7f, 0xbe, 0xc8, 0x4a, 0xdf, 0xbe, 0xcc, 0x4e, 0x3d, 0x7b, 0x99, 0x9d, - 0xfa, 0xfd, 0x65, 0x76, 0xea, 0xb3, 0xcb, 0x5d, 0x23, 0x98, 0xaf, 0xfb, 0x52, 0xec, 0xf3, 0x5e, - 0x27, 0xf2, 0xf5, 0xd2, 0x9f, 0xc8, 0x2a, 0x09, 0xfc, 0xa8, 0x77, 0xe5, 0x9f, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xca, 0xdb, 0x59, 0x1b, 0xeb, 0x14, 0x00, 0x00, + // 1557 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x58, 0x4f, 0x6f, 0x1b, 0x45, + 0x14, 0xcf, 0x36, 0x8e, 0x63, 0x3f, 0xc7, 0x4e, 0xba, 0xa4, 0xa9, 0xb3, 0x69, 0x9c, 0xd4, 0xa5, + 0x21, 0x42, 0xad, 0x9d, 0xba, 0xa5, 0x94, 0x16, 0x01, 0x8d, 0xe9, 0x9f, 0x40, 0xdd, 0x46, 0xdb, + 0x14, 0x10, 0x97, 0xd5, 0x7a, 0x77, 0xb2, 0x5e, 0xd9, 0xde, 0xb1, 0x76, 0xc6, 0x96, 0x53, 0x21, + 0x81, 0x90, 0x90, 0x38, 0x02, 0xe2, 0xc4, 0x81, 0x1b, 0x12, 0x67, 0x3e, 0x45, 0x8f, 0x15, 0x27, + 0xc4, 0xa1, 0x42, 0xed, 0x27, 0x80, 0x4f, 0x80, 0x76, 0x66, 0x76, 0xeb, 0x5d, 0xff, 0x8d, 0x2b, + 0xc4, 0xc5, 0xde, 0x79, 0xf3, 0x7e, 0x6f, 0xde, 0xbf, 0x79, 0xef, 0xed, 0xc2, 0xd6, 0x63, 0x44, + 0x75, 0xa3, 0xa6, 0xdb, 0x4e, 0x91, 0x3d, 0x61, 0x17, 0x15, 0x0d, 0x17, 0x13, 0xc2, 0x69, 0xb4, + 0x5b, 0x68, 0xb9, 0x98, 0x62, 0x79, 0x3d, 0xe0, 0x2b, 0xf8, 0x7c, 0x85, 0x97, 0x7c, 0xca, 0xb2, + 0x85, 0x2d, 0xcc, 0x38, 0x8b, 0xde, 0x13, 0x07, 0x29, 0x6f, 0x0e, 0x10, 0xde, 0xaa, 0x5b, 0x45, + 0x46, 0x22, 0xe2, 0x4f, 0xf0, 0x6e, 0x0d, 0xe3, 0xc5, 0xb6, 0xc3, 0x7e, 0xc6, 0xc8, 0x6c, 0xb9, + 0x18, 0x1f, 0x12, 0xf1, 0x27, 0x78, 0xaf, 0x8e, 0x36, 0xce, 0xd5, 0x29, 0xd2, 0x1a, 0x76, 0xd3, + 0xa6, 0xc8, 0xd5, 0x0e, 0x1b, 0xba, 0x25, 0x70, 0xf9, 0x1f, 0x24, 0x90, 0x2b, 0xc4, 0xaa, 0xd8, + 0x96, 0xc7, 0x72, 0x40, 0xc8, 0xed, 0xb6, 0x63, 0x12, 0x39, 0x0b, 0xf3, 0x86, 0x8b, 0x74, 0x8a, + 0xdd, 0xac, 0xb4, 0x29, 0x6d, 0x27, 0x55, 0x7f, 0x29, 0xaf, 0x42, 0x82, 0x89, 0xd4, 0x6c, 0x33, + 0x7b, 0x62, 0x53, 0xda, 0x9e, 0x55, 0xe7, 0xd9, 0x7a, 0xcf, 0x94, 0xef, 0x40, 0x5c, 0x6f, 0xe2, + 0xb6, 0x43, 0xb3, 0xb3, 0x1e, 0x66, 0xb7, 0xf8, 0xe4, 0xd9, 0xc6, 0xcc, 0x9f, 0xcf, 0x36, 0xde, + 0xb0, 0x6c, 0x5a, 0x6b, 0x57, 0x0b, 0x06, 0x6e, 0x16, 0x0d, 0x4c, 0x9a, 0x98, 0x88, 0xbf, 0x8b, + 0xc4, 0xac, 0x17, 0xe9, 0x51, 0x0b, 0x91, 0xc2, 0x23, 0xdb, 0xa1, 0xaa, 0x80, 0xe7, 0xcf, 0x80, + 0xd2, 0xaf, 0x93, 0x8a, 0x48, 0x0b, 0x3b, 0x04, 0xe5, 0xef, 0xc3, 0x6b, 0x15, 0x62, 0x3d, 0x6a, + 0x99, 0x7c, 0xf3, 0xa6, 0x69, 0xba, 0x88, 0x8c, 0x52, 0x79, 0x1d, 0x80, 0x12, 0xa2, 0xb5, 0xda, + 0xd5, 0x3a, 0x3a, 0x62, 0x4a, 0x27, 0xd5, 0x24, 0x25, 0x64, 0x9f, 0x11, 0xf2, 0xeb, 0xb0, 0x36, + 0x40, 0x5e, 0x70, 0xdc, 0xcf, 0x27, 0x60, 0xb9, 0x42, 0xac, 0x9b, 0xa6, 0xb9, 0xe7, 0x54, 0x71, + 0xdb, 0x31, 0x0f, 0x5c, 0xdd, 0xa8, 0x23, 0x77, 0x3a, 0x1f, 0x9d, 0x86, 0x79, 0xda, 0xd5, 0x6a, + 0x3a, 0xa9, 0x71, 0x27, 0xa9, 0x71, 0xda, 0xbd, 0xab, 0x93, 0x9a, 0xbc, 0x0b, 0x49, 0x2f, 0xf4, + 0x9a, 0xe7, 0x8e, 0x6c, 0x6c, 0x53, 0xda, 0xce, 0x94, 0xce, 0x17, 0x06, 0x64, 0x62, 0xab, 0x6e, + 0x15, 0x58, 0x8e, 0x94, 0xb1, 0xed, 0x1c, 0x1c, 0xb5, 0x90, 0x9a, 0x30, 0xc4, 0x93, 0x7c, 0x1d, + 0xe6, 0x58, 0x52, 0x64, 0xe7, 0x36, 0xa5, 0xed, 0x54, 0xe9, 0xf5, 0x61, 0x78, 0x91, 0x39, 0xfb, + 0xde, 0x9f, 0xca, 0x21, 0x9e, 0x93, 0xaa, 0x0d, 0x6c, 0xd4, 0xb9, 0x6e, 0x71, 0xee, 0x24, 0x46, + 0x61, 0xea, 0xad, 0x42, 0x82, 0x76, 0x35, 0xdb, 0x31, 0x51, 0x37, 0x3b, 0xcf, 0x4d, 0xa2, 0xdd, + 0x3d, 0x6f, 0x99, 0xcf, 0xc1, 0x99, 0x41, 0xfe, 0x09, 0x1c, 0xf8, 0xbb, 0x04, 0x27, 0x2b, 0xc4, + 0xfa, 0xb4, 0x66, 0x53, 0xd4, 0xb0, 0x09, 0xbd, 0xa5, 0x96, 0x4b, 0x3b, 0x23, 0xbc, 0x77, 0x0e, + 0xd2, 0xc8, 0x35, 0x4a, 0x3b, 0x9a, 0xce, 0x23, 0x21, 0x22, 0xb6, 0xc0, 0x88, 0x7e, 0xb4, 0x7b, + 0x5d, 0x3c, 0x1b, 0x76, 0xb1, 0x0c, 0x31, 0x47, 0x6f, 0x72, 0x27, 0x26, 0x55, 0xf6, 0x2c, 0xaf, + 0x40, 0x9c, 0x1c, 0x35, 0xab, 0xb8, 0xc1, 0x5c, 0x93, 0x54, 0xc5, 0x4a, 0x56, 0x20, 0x61, 0x22, + 0xc3, 0x6e, 0xea, 0x0d, 0xc2, 0x6c, 0x4e, 0xab, 0xc1, 0x5a, 0x5e, 0x83, 0xa4, 0xa5, 0x13, 0x7e, + 0x6b, 0x84, 0xcd, 0x09, 0x4b, 0x27, 0xf7, 0xbc, 0x75, 0x5e, 0x83, 0xd5, 0x3e, 0x9b, 0x7c, 0x8b, + 0x3d, 0x0b, 0x1e, 0x87, 0x2c, 0xe0, 0x16, 0x2e, 0x3c, 0xee, 0xb5, 0x60, 0x1d, 0xc0, 0x30, 0x02, + 0x9f, 0x8a, 0xac, 0xf4, 0x28, 0xdc, 0xab, 0x7f, 0x4b, 0x70, 0x8a, 0xbb, 0xf5, 0x41, 0x9b, 0xbe, + 0x7a, 0xde, 0x2d, 0xc3, 0x9c, 0x83, 0x1d, 0x03, 0x31, 0x67, 0xc5, 0x54, 0xbe, 0xe8, 0xcd, 0xc6, + 0x58, 0x28, 0x1b, 0xff, 0x9f, 0x4c, 0x7a, 0x0f, 0xd6, 0x07, 0x9a, 0x1c, 0x38, 0x76, 0x1d, 0xc0, + 0x26, 0x9a, 0x8b, 0x9a, 0xb8, 0x83, 0x4c, 0x66, 0x7d, 0x42, 0x4d, 0xda, 0x44, 0xe5, 0x84, 0x3c, + 0x82, 0x6c, 0x85, 0x58, 0x7c, 0xf5, 0xdf, 0x79, 0x2d, 0x9f, 0x87, 0xcd, 0x61, 0xc7, 0x04, 0x49, + 0xff, 0xab, 0x04, 0x8b, 0x15, 0x62, 0x7d, 0x82, 0x29, 0xba, 0xa3, 0x93, 0x7d, 0xd7, 0x36, 0xd0, + 0xd4, 0x2a, 0xb4, 0x3c, 0xb4, 0xaf, 0x02, 0x5b, 0xc8, 0x67, 0x61, 0xa1, 0xe5, 0xda, 0xd8, 0xb5, + 0xe9, 0x91, 0x76, 0x88, 0x10, 0xf3, 0x72, 0x4c, 0x4d, 0xf9, 0xb4, 0xdb, 0x88, 0xb1, 0xf0, 0x30, + 0x38, 0xed, 0x66, 0x15, 0xb9, 0x2c, 0xc0, 0x31, 0x35, 0xc5, 0x68, 0xf7, 0x19, 0xe9, 0xa3, 0x58, + 0x62, 0x6e, 0x29, 0x9e, 0x5f, 0x85, 0xd3, 0x11, 0x4d, 0x03, 0x2b, 0x7e, 0x89, 0x07, 0x56, 0xf8, + 0x86, 0x8e, 0xb0, 0x62, 0x0d, 0x58, 0xfe, 0xf2, 0xb8, 0xf3, 0x84, 0x4e, 0x78, 0x04, 0x16, 0xf6, + 0x2b, 0xb0, 0x82, 0xab, 0x04, 0xb9, 0x1d, 0x64, 0x6a, 0x58, 0xc8, 0xea, 0xad, 0x83, 0xcb, 0xfe, + 0xae, 0x7f, 0x10, 0x43, 0x95, 0x21, 0xd7, 0x8f, 0x12, 0xd9, 0x85, 0x6c, 0xab, 0x46, 0x85, 0x59, + 0x6b, 0x51, 0xf4, 0x2e, 0xcb, 0x37, 0xc6, 0x22, 0xdf, 0x00, 0xa5, 0x5f, 0x88, 0x77, 0xb5, 0xdb, + 0x04, 0x99, 0x59, 0x60, 0x02, 0x4e, 0x47, 0x05, 0xdc, 0xd1, 0xc9, 0x23, 0x82, 0x4c, 0xf9, 0x2b, + 0x09, 0xce, 0xf7, 0xa3, 0xd1, 0xe1, 0x21, 0x32, 0xa8, 0xdd, 0x41, 0x4c, 0x0e, 0x0f, 0x50, 0x8a, + 0x35, 0xbd, 0x82, 0x68, 0x7a, 0x5b, 0x13, 0x34, 0xbd, 0x3d, 0x87, 0xaa, 0x67, 0xa3, 0x07, 0xdf, + 0xf2, 0x45, 0x07, 0x79, 0xb3, 0x3f, 0x5e, 0x03, 0x5e, 0xa4, 0x16, 0x98, 0x29, 0x23, 0x25, 0xb2, + 0xea, 0x25, 0x63, 0xc8, 0x74, 0xf4, 0x46, 0x1b, 0x69, 0x2e, 0x32, 0x90, 0xed, 0xdd, 0x25, 0x56, + 0x16, 0x77, 0xef, 0x1e, 0xb3, 0x63, 0xff, 0xf3, 0x6c, 0xe3, 0xd4, 0x91, 0xde, 0x6c, 0x5c, 0xcf, + 0x87, 0xc5, 0xe5, 0xd5, 0x34, 0x23, 0xa8, 0x62, 0x2d, 0x7f, 0x08, 0x71, 0x42, 0x75, 0xda, 0xe6, + 0x55, 0x36, 0x53, 0xba, 0x30, 0xb4, 0xb5, 0xf1, 0x41, 0x49, 0x00, 0x1f, 0x32, 0x8c, 0x2a, 0xb0, + 0xf2, 0x79, 0xc8, 0x04, 0xf6, 0x33, 0x46, 0x51, 0x40, 0xd2, 0x3e, 0xb5, 0xec, 0x11, 0xe5, 0x0b, + 0x20, 0x07, 0x6c, 0x5e, 0xe3, 0xe7, 0x57, 0x38, 0xc1, 0x9c, 0xb3, 0xe4, 0xef, 0x1c, 0x10, 0x72, + 0x9f, 0xd5, 0xc0, 0x50, 0xe3, 0x4d, 0x4e, 0xd5, 0x78, 0x7b, 0xae, 0x90, 0xef, 0xf3, 0xe0, 0x0a, + 0xfd, 0x14, 0x83, 0x8c, 0xd8, 0x13, 0xfd, 0x71, 0xc4, 0x0d, 0xf2, 0xda, 0x14, 0x72, 0x4c, 0xe4, + 0x8a, 0xeb, 0x23, 0x56, 0xf2, 0x16, 0x2c, 0xf2, 0x27, 0x2d, 0xd2, 0xf4, 0xd2, 0x9c, 0x5c, 0x16, + 0xc5, 0x42, 0x81, 0x84, 0x08, 0x81, 0x2b, 0x0a, 0x7a, 0xb0, 0xf6, 0x9c, 0xe7, 0x3f, 0x0b, 0xe7, + 0xcd, 0x71, 0x11, 0x3e, 0x95, 0x3b, 0xef, 0xe5, 0x10, 0x17, 0x7f, 0xa5, 0x21, 0xce, 0xb3, 0xb2, + 0x89, 0x08, 0xd1, 0x2d, 0xee, 0xfa, 0xa4, 0xea, 0x2f, 0xbd, 0xca, 0x64, 0x3b, 0x3d, 0x05, 0x20, + 0xc9, 0xb6, 0x53, 0x82, 0xc6, 0xee, 0xfd, 0x0e, 0x2c, 0xfb, 0x2c, 0xa1, 0xdb, 0xce, 0x2f, 0xab, + 0x2c, 0xf6, 0x7a, 0x2f, 0x79, 0xa8, 0x5b, 0xa7, 0x18, 0x5b, 0xd0, 0xad, 0xc3, 0x31, 0x5e, 0x98, + 0x6e, 0xb8, 0x5a, 0x83, 0x24, 0xed, 0x6a, 0xd8, 0xb5, 0x2d, 0xdb, 0xc9, 0xa6, 0xb9, 0x73, 0x69, + 0xf7, 0x01, 0x5b, 0x7b, 0x55, 0x5a, 0x27, 0x04, 0xd1, 0x6c, 0x86, 0x6d, 0xf0, 0x85, 0xbc, 0x01, + 0x29, 0xd4, 0x41, 0x0e, 0x15, 0xdd, 0x6e, 0x91, 0x69, 0x05, 0x8c, 0xc4, 0x1b, 0x5e, 0x16, 0x56, + 0xc2, 0xb9, 0x11, 0xa4, 0xcd, 0x3d, 0x36, 0x33, 0xdd, 0xac, 0x62, 0x97, 0x3e, 0xa4, 0x6d, 0xa3, + 0x5e, 0x2e, 0x1f, 0x7c, 0x36, 0x7a, 0xc4, 0x1d, 0x35, 0x4c, 0xac, 0xb1, 0x69, 0x25, 0x2c, 0x2d, + 0x38, 0xaa, 0xc3, 0xe6, 0x5b, 0x15, 0x1d, 0xb6, 0x1d, 0x93, 0xb1, 0x20, 0xf3, 0x95, 0x4e, 0xe3, + 0x99, 0xe6, 0x49, 0x0b, 0xe6, 0x1f, 0x5e, 0xe2, 0xd3, 0x9c, 0x2a, 0x06, 0x20, 0x31, 0x37, 0xf6, + 0x9d, 0xfb, 0xf2, 0xe6, 0x48, 0x4c, 0x6b, 0x3e, 0x98, 0xab, 0x3a, 0x45, 0xf7, 0xf8, 0xfb, 0xcb, + 0x6d, 0xef, 0xf5, 0x65, 0x84, 0x76, 0x06, 0xc8, 0xfd, 0xaf, 0x3b, 0x4c, 0xcb, 0x54, 0xa9, 0x58, + 0x18, 0xf9, 0x72, 0x57, 0x88, 0x1e, 0xb3, 0x1b, 0xf3, 0xd2, 0x5f, 0x5d, 0x72, 0x23, 0xf4, 0xfc, + 0x39, 0x38, 0x3b, 0x54, 0x37, 0xdf, 0x82, 0xd2, 0x6f, 0x0b, 0x30, 0x5b, 0x21, 0x96, 0xfc, 0xad, + 0x04, 0xf2, 0x80, 0x41, 0xee, 0xca, 0x18, 0x65, 0x06, 0xce, 0x42, 0xca, 0xbb, 0xd3, 0xa0, 0x82, + 0x09, 0xea, 0x1b, 0x09, 0x4e, 0xf6, 0xbf, 0xca, 0x5c, 0x9e, 0x48, 0x66, 0x18, 0xa4, 0xdc, 0x98, + 0x02, 0x14, 0xe8, 0xf1, 0xbd, 0x04, 0xa7, 0x06, 0x0f, 0x6a, 0x6f, 0x8f, 0x17, 0x3b, 0x10, 0xa8, + 0xbc, 0x3f, 0x25, 0x30, 0xd0, 0xa9, 0x03, 0x0b, 0xa1, 0x79, 0xad, 0x30, 0x5e, 0x60, 0x2f, 0xbf, + 0x72, 0xf5, 0x78, 0xfc, 0xd1, 0x73, 0x83, 0x09, 0x6b, 0xc2, 0x73, 0x7d, 0xfe, 0x49, 0xcf, 0x8d, + 0xb6, 0x26, 0x99, 0x40, 0xaa, 0xb7, 0x2d, 0x5d, 0x9c, 0x4c, 0x8c, 0x60, 0x57, 0xde, 0x3a, 0x16, + 0x7b, 0x70, 0xe8, 0x17, 0x90, 0x89, 0xbc, 0x09, 0xee, 0x8c, 0x17, 0x14, 0x46, 0x28, 0xd7, 0x8e, + 0x8b, 0x08, 0x4e, 0xff, 0x5a, 0x82, 0xa5, 0xbe, 0x2f, 0x07, 0xa5, 0xf1, 0xe2, 0xa2, 0x18, 0xe5, + 0xfa, 0xf1, 0x31, 0x81, 0x12, 0x5f, 0xc2, 0x62, 0xf4, 0x7b, 0xcb, 0xa5, 0xf1, 0xe2, 0x22, 0x10, + 0xe5, 0x9d, 0x63, 0x43, 0x7a, 0x63, 0x10, 0xe9, 0x2c, 0x13, 0xc4, 0x20, 0x8c, 0x98, 0x24, 0x06, + 0x83, 0xfb, 0x0d, 0x2b, 0x41, 0xfd, 0xdd, 0xe6, 0xf2, 0x24, 0xb7, 0x37, 0x02, 0x9a, 0xa4, 0x04, + 0x0d, 0xed, 0x2f, 0xf2, 0x8f, 0x12, 0xac, 0x0c, 0x69, 0x2e, 0xd7, 0x26, 0x8d, 0x6e, 0x14, 0xa9, + 0x7c, 0x30, 0x2d, 0xd2, 0x57, 0x6b, 0xf7, 0xe3, 0x27, 0xcf, 0x73, 0xd2, 0xd3, 0xe7, 0x39, 0xe9, + 0xaf, 0xe7, 0x39, 0xe9, 0xbb, 0x17, 0xb9, 0x99, 0xa7, 0x2f, 0x72, 0x33, 0x7f, 0xbc, 0xc8, 0xcd, + 0x7c, 0x7e, 0xa9, 0x67, 0x04, 0xf3, 0x64, 0x5f, 0x8c, 0x7c, 0xef, 0xeb, 0x86, 0x3e, 0x67, 0x7a, + 0x13, 0x59, 0x35, 0xce, 0xbe, 0xf2, 0x5d, 0xfe, 0x37, 0x00, 0x00, 0xff, 0xff, 0xda, 0xb5, 0x92, + 0x0a, 0xfc, 0x14, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -2551,12 +2552,10 @@ func (m *MsgVoteGasPrice) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.Supply) > 0 { - i -= len(m.Supply) - copy(dAtA[i:], m.Supply) - i = encodeVarintTx(dAtA, i, uint64(len(m.Supply))) + if m.PriorityFee != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.PriorityFee)) i-- - dAtA[i] = 0x2a + dAtA[i] = 0x30 } if m.BlockNumber != 0 { i = encodeVarintTx(dAtA, i, uint64(m.BlockNumber)) @@ -3304,9 +3303,8 @@ func (m *MsgVoteGasPrice) Size() (n int) { if m.BlockNumber != 0 { n += 1 + sovTx(uint64(m.BlockNumber)) } - l = len(m.Supply) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) + if m.PriorityFee != 0 { + n += 1 + sovTx(uint64(m.PriorityFee)) } return n } @@ -5111,11 +5109,11 @@ func (m *MsgVoteGasPrice) Unmarshal(dAtA []byte) error { break } } - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Supply", wireType) + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PriorityFee", wireType) } - var stringLen uint64 + m.PriorityFee = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -5125,24 +5123,11 @@ func (m *MsgVoteGasPrice) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + m.PriorityFee |= uint64(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Supply = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) diff --git a/zetaclient/chains/bitcoin/observer/observer.go b/zetaclient/chains/bitcoin/observer/observer.go index 4b07974052..519b3b99d8 100644 --- a/zetaclient/chains/bitcoin/observer/observer.go +++ b/zetaclient/chains/bitcoin/observer/observer.go @@ -386,8 +386,11 @@ func (ob *Observer) PostGasPrice(ctx context.Context) error { return err } + // UTXO has no concept of priority fee (like eth) + const priorityFee = 0 + // #nosec G115 always positive - _, err = ob.ZetacoreClient().PostVoteGasPrice(ctx, ob.Chain(), feeRateEstimated, "100", uint64(blockNumber)) + _, err = ob.ZetacoreClient().PostVoteGasPrice(ctx, ob.Chain(), feeRateEstimated, priorityFee, uint64(blockNumber)) if err != nil { ob.logger.GasPrice.Err(err).Msg("err PostGasPrice") return err diff --git a/zetaclient/chains/evm/observer/observer.go b/zetaclient/chains/evm/observer/observer.go index dbfafd23e1..d49e5a53a3 100644 --- a/zetaclient/chains/evm/observer/observer.go +++ b/zetaclient/chains/evm/observer/observer.go @@ -28,7 +28,6 @@ import ( "github.com/zeta-chain/zetacore/zetaclient/config" "github.com/zeta-chain/zetacore/zetaclient/db" "github.com/zeta-chain/zetacore/zetaclient/metrics" - clienttypes "github.com/zeta-chain/zetacore/zetaclient/types" ) var _ interfaces.ChainObserver = (*Observer)(nil) @@ -38,6 +37,8 @@ type Observer struct { // base.Observer implements the base chain observer base.Observer + priorityFeeConfig + // evmClient is the EVM client for the observed chain evmClient interfaces.EVMRPCClient @@ -54,6 +55,12 @@ type Observer struct { outboundConfirmedTransactions map[string]*ethtypes.Transaction } +// priorityFeeConfig is the configuration for priority fee +type priorityFeeConfig struct { + checked bool + supported bool +} + // NewObserver returns a new EVM chain observer func NewObserver( ctx context.Context, @@ -90,6 +97,7 @@ func NewObserver( outboundPendingTransactions: make(map[string]*ethtypes.Transaction), outboundConfirmedReceipts: make(map[string]*ethtypes.Receipt), outboundConfirmedTransactions: make(map[string]*ethtypes.Transaction), + priorityFeeConfig: priorityFeeConfig{}, } // load last block scanned @@ -288,75 +296,6 @@ func (ob *Observer) CheckTxInclusion(tx *ethtypes.Transaction, receipt *ethtypes return nil } -// WatchGasPrice watches evm chain for gas prices and post to zetacore -// TODO(revamp): move ticker to ticker file -// TODO(revamp): move inner logic to a separate function -func (ob *Observer) WatchGasPrice(ctx context.Context) error { - // report gas price right away as the ticker takes time to kick in - err := ob.PostGasPrice(ctx) - if err != nil { - ob.Logger().GasPrice.Error().Err(err).Msgf("PostGasPrice error for chain %d", ob.Chain().ChainId) - } - - // start gas price ticker - ticker, err := clienttypes.NewDynamicTicker( - fmt.Sprintf("EVM_WatchGasPrice_%d", ob.Chain().ChainId), - ob.GetChainParams().GasPriceTicker, - ) - if err != nil { - ob.Logger().GasPrice.Error().Err(err).Msg("NewDynamicTicker error") - return err - } - ob.Logger().GasPrice.Info().Msgf("WatchGasPrice started for chain %d with interval %d", - ob.Chain().ChainId, ob.GetChainParams().GasPriceTicker) - - defer ticker.Stop() - for { - select { - case <-ticker.C(): - if !ob.GetChainParams().IsSupported { - continue - } - err = ob.PostGasPrice(ctx) - if err != nil { - ob.Logger().GasPrice.Error().Err(err).Msgf("PostGasPrice error for chain %d", ob.Chain().ChainId) - } - ticker.UpdateInterval(ob.GetChainParams().GasPriceTicker, ob.Logger().GasPrice) - case <-ob.StopChannel(): - ob.Logger().GasPrice.Info().Msg("WatchGasPrice stopped") - return nil - } - } -} - -// PostGasPrice posts gas price to zetacore -// TODO(revamp): move to gas price file -func (ob *Observer) PostGasPrice(ctx context.Context) error { - // GAS PRICE - gasPrice, err := ob.evmClient.SuggestGasPrice(ctx) - if err != nil { - ob.Logger().GasPrice.Err(err).Msg("Err SuggestGasPrice:") - return err - } - blockNum, err := ob.evmClient.BlockNumber(ctx) - if err != nil { - ob.Logger().GasPrice.Err(err).Msg("Err Fetching Most recent Block : ") - return err - } - - // SUPPLY - supply := "100" // lockedAmount on ETH, totalSupply on other chains - - zetaHash, err := ob.ZetacoreClient().PostVoteGasPrice(ctx, ob.Chain(), gasPrice.Uint64(), supply, blockNum) - if err != nil { - ob.Logger().GasPrice.Err(err).Msg("PostGasPrice to zetacore failed") - return err - } - _ = zetaHash - - return nil -} - // TransactionByHash query transaction by hash via JSON-RPC // TODO(revamp): update this method as a pure RPC method that takes two parameters (jsonRPC, and txHash) and move to upper package to file rpc.go func (ob *Observer) TransactionByHash(txHash string) (*ethrpc.Transaction, bool, error) { diff --git a/zetaclient/chains/evm/observer/observer_gas.go b/zetaclient/chains/evm/observer/observer_gas.go new file mode 100644 index 0000000000..8bbc32d3a0 --- /dev/null +++ b/zetaclient/chains/evm/observer/observer_gas.go @@ -0,0 +1,147 @@ +package observer + +import ( + "context" + "fmt" + "math/big" + + "github.com/pkg/errors" + + clienttypes "github.com/zeta-chain/zetacore/zetaclient/types" +) + +// WatchGasPrice watches evm chain for gas prices and post to zetacore +// TODO(revamp): move inner logic to a separate function +func (ob *Observer) WatchGasPrice(ctx context.Context) error { + // report gas price right away as the ticker takes time to kick in + err := ob.PostGasPrice(ctx) + if err != nil { + ob.Logger().GasPrice.Error().Err(err).Msgf("PostGasPrice error for chain %d", ob.Chain().ChainId) + } + + // start gas price ticker + ticker, err := clienttypes.NewDynamicTicker( + fmt.Sprintf("EVM_WatchGasPrice_%d", ob.Chain().ChainId), + ob.GetChainParams().GasPriceTicker, + ) + if err != nil { + ob.Logger().GasPrice.Error().Err(err).Msg("NewDynamicTicker error") + return err + } + ob.Logger().GasPrice.Info().Msgf("WatchGasPrice started for chain %d with interval %d", + ob.Chain().ChainId, ob.GetChainParams().GasPriceTicker) + + defer ticker.Stop() + for { + select { + case <-ticker.C(): + if !ob.GetChainParams().IsSupported { + continue + } + err = ob.PostGasPrice(ctx) + if err != nil { + ob.Logger().GasPrice.Error().Err(err).Msgf("PostGasPrice error for chain %d", ob.Chain().ChainId) + } + ticker.UpdateInterval(ob.GetChainParams().GasPriceTicker, ob.Logger().GasPrice) + case <-ob.StopChannel(): + ob.Logger().GasPrice.Info().Msg("WatchGasPrice stopped") + return nil + } + } +} + +// PostGasPrice posts gas price to zetacore. +func (ob *Observer) PostGasPrice(ctx context.Context) error { + // GAS PRICE + gasPrice, err := ob.evmClient.SuggestGasPrice(ctx) + if err != nil { + return errors.Wrap(err, "unable to suggest gas price") + } + + // PRIORITY FEE (EIP-1559) + priorityFee, err := ob.determinePriorityFee(ctx) + if err != nil { + return errors.Wrap(err, "unable to determine priority fee") + } + + blockNum, err := ob.evmClient.BlockNumber(ctx) + if err != nil { + return errors.Wrap(err, "unable to get block number") + } + + _, err = ob. + ZetacoreClient(). + PostVoteGasPrice(ctx, ob.Chain(), gasPrice.Uint64(), priorityFee.Uint64(), blockNum) + + if err != nil { + return errors.Wrap(err, "unable to post vote for gas price") + } + + return nil +} + +// determinePriorityFee determines the chain priority fee. +// Returns zero for non EIP-1559 (London fork) chains. +func (ob *Observer) determinePriorityFee(ctx context.Context) (*big.Int, error) { + supported, err := ob.supportsPriorityFee(ctx) + switch { + case err != nil: + return nil, err + case !supported: + // noop + return big.NewInt(0), nil + } + + fee, err := ob.evmClient.SuggestGasTipCap(ctx) + if err != nil { + return nil, errors.Wrap(err, "unable to suggest gas tip cap") + } + + return fee, nil +} + +// supportsPriorityFee checks if the chain supports EIP-1559 (London fork). +// uses cache so actual RPC call is made only once. +func (ob *Observer) supportsPriorityFee(ctx context.Context) (bool, error) { + // noop + if ob.priorityFeeConfig.checked { + return ob.priorityFeeConfig.supported, nil + } + + baseFee, err := ob.getChainBaseFee(ctx) + if err != nil { + return false, errors.Wrap(err, "unable to get base fee") + } + + ob.Logger().GasPrice.Info(). + Int64("observer.chain_id", ob.Chain().ChainId). + Str("observer.base_fee", baseFee.String()). + Msg("Fetched base fee for chain") + + // EIP-1559 is supported if base fee is not zero. + // Not that, for example, BSC supports EIP-1559 but base fee is zero. + isSupported := baseFee != nil + + ob.Mu().Lock() + defer ob.Mu().Unlock() + + ob.priorityFeeConfig.checked = true + ob.priorityFeeConfig.checked = isSupported + + return isSupported, nil +} + +// getChainBaseFee fetches baseFee from latest block's header. +func (ob *Observer) getChainBaseFee(ctx context.Context) (*big.Int, error) { + // get latest block + header, err := ob.evmClient.HeaderByNumber(ctx, nil) + if err != nil { + return nil, errors.Wrap(err, "unable to get latest block header") + } + + if header.BaseFee == nil { + return big.NewInt(0), nil + } + + return header.BaseFee, nil +} diff --git a/zetaclient/chains/evm/observer/observer_gas_test.go b/zetaclient/chains/evm/observer/observer_gas_test.go new file mode 100644 index 0000000000..ce0b681d43 --- /dev/null +++ b/zetaclient/chains/evm/observer/observer_gas_test.go @@ -0,0 +1,115 @@ +package observer_test + +import ( + "context" + "math/big" + "testing" + + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/zeta-chain/zetacore/pkg/chains" + "github.com/zeta-chain/zetacore/zetaclient/testutils/mocks" +) + +func TestPostGasPrice(t *testing.T) { + const ( + gwei = 10e9 + blockNumber = 1000 + anything = mock.Anything + ) + + ctx := context.Background() + + t.Run("Pre EIP-1559 doesn't support priorityFee", func(t *testing.T) { + // ARRANGE + // Given ETH rpc mock + ethRPC := mocks.NewMockEvmClient().WithBlockNumber(blockNumber) + + // Given zetacore client mock + zetacoreClient := mocks.NewZetacoreClient(t).WithZetaChain() + + // Given an observer + chain := chains.Ethereum + confirmation := uint64(10) + chainParam := mocks.MockChainParams(chain.ChainId, confirmation) + + observer := MockEVMObserver(t, chain, ethRPC, nil, zetacoreClient, nil, blockNumber, chainParam) + + // Given empty baseFee from RPC + ethRPC.WithHeader(ðtypes.Header{BaseFee: nil}) + + // Given gas price from RPC + ethRPC.WithSuggestGasPrice(big.NewInt(3 * gwei)) + + // Given mock collector for zetacore call + // PostVoteGasPrice(ctx, chain, gasPrice, priorityFee, blockNum) + var gasPrice, priorityFee uint64 + collector := func(args mock.Arguments) { + gasPrice = args.Get(2).(uint64) + priorityFee = args.Get(3).(uint64) + } + + zetacoreClient. + On("PostVoteGasPrice", anything, anything, anything, anything, anything). + Run(collector). + Return("0xABC123...", nil) + + // ACT + err := observer.PostGasPrice(ctx) + + // ASSERT + assert.NoError(t, err) + + // Check that gas price is posted with proper gasPrice and priorityFee + assert.Equal(t, uint64(3*gwei), gasPrice) + assert.Equal(t, uint64(0), priorityFee) + }) + + t.Run("Post EIP-1559 supports priorityFee", func(t *testing.T) { + // ARRANGE + // Given ETH rpc mock + ethRPC := mocks.NewMockEvmClient().WithBlockNumber(blockNumber) + + // Given zetacore client mock + zetacoreClient := mocks.NewZetacoreClient(t).WithZetaChain() + + // Given an observer + chain := chains.Ethereum + confirmation := uint64(10) + chainParam := mocks.MockChainParams(chain.ChainId, confirmation) + + observer := MockEVMObserver(t, chain, ethRPC, nil, zetacoreClient, nil, blockNumber, chainParam) + + // Given 1 gwei baseFee from RPC + ethRPC.WithHeader(ðtypes.Header{BaseFee: big.NewInt(gwei)}) + + // Given gasPrice and priorityFee from RPC + ethRPC. + WithSuggestGasPrice(big.NewInt(3 * gwei)). + WithSuggestGasTipCap(big.NewInt(2 * gwei)) + + // Given mock collector for zetacore call + // PostVoteGasPrice(ctx, chain, gasPrice, priorityFee, blockNum) + var gasPrice, priorityFee uint64 + collector := func(args mock.Arguments) { + gasPrice = args.Get(2).(uint64) + priorityFee = args.Get(3).(uint64) + } + + zetacoreClient. + On("PostVoteGasPrice", anything, anything, anything, anything, anything). + Run(collector). + Return("0xABC123...", nil) + + // ACT + err := observer.PostGasPrice(ctx) + + // ASSERT + assert.NoError(t, err) + + // Check that gas price is posted with proper gasPrice and priorityFee + assert.Equal(t, uint64(3*gwei), gasPrice) + assert.Equal(t, uint64(2*gwei), priorityFee) + }) +} diff --git a/zetaclient/chains/interfaces/interfaces.go b/zetaclient/chains/interfaces/interfaces.go index f0da266759..82125ca619 100644 --- a/zetaclient/chains/interfaces/interfaces.go +++ b/zetaclient/chains/interfaces/interfaces.go @@ -81,9 +81,7 @@ type ZetacoreVoter interface { PostVoteGasPrice( ctx context.Context, chain chains.Chain, - gasPrice uint64, - supply string, - blockNum uint64, + gasPrice, priorityFee, blockNum uint64, ) (string, error) PostVoteInbound( ctx context.Context, diff --git a/zetaclient/testutils/mocks/evm_rpc.go b/zetaclient/testutils/mocks/evm_rpc.go index e6daff0f13..5cf856e16f 100644 --- a/zetaclient/testutils/mocks/evm_rpc.go +++ b/zetaclient/testutils/mocks/evm_rpc.go @@ -34,6 +34,8 @@ type MockEvmClient struct { err error blockNumber uint64 header *ethtypes.Header + gasPrice *big.Int + priorityFee *big.Int Receipts []*ethtypes.Receipt } @@ -92,6 +94,11 @@ func (e *MockEvmClient) SuggestGasPrice(_ context.Context) (*big.Int, error) { if e.err != nil { return nil, e.err } + + if e.gasPrice != nil { + return e.gasPrice, nil + } + return big.NewInt(0), nil } @@ -99,6 +106,11 @@ func (e *MockEvmClient) SuggestGasTipCap(_ context.Context) (*big.Int, error) { if e.err != nil { return nil, e.err } + + if e.priorityFee != nil { + return e.priorityFee, nil + } + return big.NewInt(0), nil } @@ -204,3 +216,13 @@ func (e *MockEvmClient) WithReceipts(receipts []*ethtypes.Receipt) *MockEvmClien e.Receipts = append(e.Receipts, receipts...) return e } + +func (e *MockEvmClient) WithSuggestGasPrice(price *big.Int) *MockEvmClient { + e.gasPrice = price + return e +} + +func (e *MockEvmClient) WithSuggestGasTipCap(price *big.Int) *MockEvmClient { + e.priorityFee = price + return e +} diff --git a/zetaclient/testutils/mocks/zetacore_client.go b/zetaclient/testutils/mocks/zetacore_client.go index f1e0b7fc3e..b1dbd3f741 100644 --- a/zetaclient/testutils/mocks/zetacore_client.go +++ b/zetaclient/testutils/mocks/zetacore_client.go @@ -654,9 +654,9 @@ func (_m *ZetacoreClient) PostVoteBlockHeader(ctx context.Context, chainID int64 return r0, r1 } -// PostVoteGasPrice provides a mock function with given fields: ctx, chain, gasPrice, supply, blockNum -func (_m *ZetacoreClient) PostVoteGasPrice(ctx context.Context, chain chains.Chain, gasPrice uint64, supply string, blockNum uint64) (string, error) { - ret := _m.Called(ctx, chain, gasPrice, supply, blockNum) +// PostVoteGasPrice provides a mock function with given fields: ctx, chain, gasPrice, priorityFee, blockNum +func (_m *ZetacoreClient) PostVoteGasPrice(ctx context.Context, chain chains.Chain, gasPrice uint64, priorityFee uint64, blockNum uint64) (string, error) { + ret := _m.Called(ctx, chain, gasPrice, priorityFee, blockNum) if len(ret) == 0 { panic("no return value specified for PostVoteGasPrice") @@ -664,17 +664,17 @@ func (_m *ZetacoreClient) PostVoteGasPrice(ctx context.Context, chain chains.Cha var r0 string var r1 error - if rf, ok := ret.Get(0).(func(context.Context, chains.Chain, uint64, string, uint64) (string, error)); ok { - return rf(ctx, chain, gasPrice, supply, blockNum) + if rf, ok := ret.Get(0).(func(context.Context, chains.Chain, uint64, uint64, uint64) (string, error)); ok { + return rf(ctx, chain, gasPrice, priorityFee, blockNum) } - if rf, ok := ret.Get(0).(func(context.Context, chains.Chain, uint64, string, uint64) string); ok { - r0 = rf(ctx, chain, gasPrice, supply, blockNum) + if rf, ok := ret.Get(0).(func(context.Context, chains.Chain, uint64, uint64, uint64) string); ok { + r0 = rf(ctx, chain, gasPrice, priorityFee, blockNum) } else { r0 = ret.Get(0).(string) } - if rf, ok := ret.Get(1).(func(context.Context, chains.Chain, uint64, string, uint64) error); ok { - r1 = rf(ctx, chain, gasPrice, supply, blockNum) + if rf, ok := ret.Get(1).(func(context.Context, chains.Chain, uint64, uint64, uint64) error); ok { + r1 = rf(ctx, chain, gasPrice, priorityFee, blockNum) } else { r1 = ret.Error(1) } diff --git a/zetaclient/zetacore/client_vote.go b/zetaclient/zetacore/client_vote.go index a8d406d177..49eea1f813 100644 --- a/zetaclient/zetacore/client_vote.go +++ b/zetaclient/zetacore/client_vote.go @@ -46,9 +46,7 @@ func (c *Client) PostVoteBlockHeader( func (c *Client) PostVoteGasPrice( ctx context.Context, chain chains.Chain, - gasPrice uint64, - supply string, - blockNum uint64, + gasPrice uint64, priorityFee, blockNum uint64, ) (string, error) { // apply gas price multiplier for the chain multiplier, err := GasPriceMultiplier(chain) @@ -59,7 +57,7 @@ func (c *Client) PostVoteGasPrice( // #nosec G115 always in range gasPrice = uint64(float64(gasPrice) * multiplier) signerAddress := c.keys.GetOperatorAddress().String() - msg := types.NewMsgVoteGasPrice(signerAddress, chain.ChainId, gasPrice, supply, blockNum) + msg := types.NewMsgVoteGasPrice(signerAddress, chain.ChainId, gasPrice, priorityFee, blockNum) authzMsg, authzSigner, err := WrapMessageWithAuthz(msg) if err != nil { diff --git a/zetaclient/zetacore/tx_test.go b/zetaclient/zetacore/tx_test.go index 5af6699670..bf78a7ab59 100644 --- a/zetaclient/zetacore/tx_test.go +++ b/zetaclient/zetacore/tx_test.go @@ -147,7 +147,7 @@ func TestZetacore_PostGasPrice(t *testing.T) { ) t.Run("post gas price success", func(t *testing.T) { - hash, err := client.PostVoteGasPrice(ctx, chains.BscMainnet, 1000000, "100", 1234) + hash, err := client.PostVoteGasPrice(ctx, chains.BscMainnet, 1000000, 0, 1234) require.NoError(t, err) require.Equal(t, sampleHash, hash) })