Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(crosschain): store priorityFee (GasTipCap) for EVM chains #2483

Merged
merged 23 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions docs/openapi/openapi.swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -57260,6 +57267,8 @@ definitions:
format: uint64
gas_price:
type: string
gas_priority_fee:
type: string
hash:
type: string
title: |-
Expand Down
2 changes: 1 addition & 1 deletion docs/spec/crosschain/messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
```

Expand Down
21 changes: 21 additions & 0 deletions pkg/math/cosmos_uint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package math

import "cosmossdk.io/math"
swift1337 marked this conversation as resolved.
Show resolved Hide resolved

// 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
}
}
42 changes: 42 additions & 0 deletions pkg/math/cosmos_uint_test.go
Original file line number Diff line number Diff line change
@@ -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(),
)
})
}
}
53 changes: 53 additions & 0 deletions pkg/math/slice.go
Original file line number Diff line number Diff line change
@@ -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
}
75 changes: 75 additions & 0 deletions pkg/math/slice_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
})
}

}
8 changes: 6 additions & 2 deletions proto/zetachain/zetacore/crosschain/cross_chain_tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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 {
Expand Down
6 changes: 6 additions & 0 deletions proto/zetachain/zetacore/crosschain/gas_price.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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;
swift1337 marked this conversation as resolved.
Show resolved Hide resolved
}
7 changes: 6 additions & 1 deletion proto/zetachain/zetacore/crosschain/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand Down
13 changes: 7 additions & 6 deletions testutil/network/genesis_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{},
},
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,11 @@ export declare class OutboundParams extends Message<OutboundParams> {
*/
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
Expand Down
9 changes: 9 additions & 0 deletions typescript/zetachain/zetacore/crosschain/gas_price_pb.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,19 @@ export declare class GasPrice extends Message<GasPrice> {
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<GasPrice>);

static readonly runtime: typeof proto3;
Expand Down
8 changes: 4 additions & 4 deletions typescript/zetachain/zetacore/crosschain/tx_pb.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -420,14 +420,14 @@ export declare class MsgVoteGasPrice extends Message<MsgVoteGasPrice> {
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<MsgVoteGasPrice>);

Expand Down
Loading
Loading