Skip to content

Commit 4ff05b3

Browse files
authored
feat: add relayer fee settings (#1197)
# Related Github tickets - VolumeFi#1710 # Background > This change adds the concept of individual > relayer fees that may be set by any active > validator for any supported target chain. # Testing completed - [x] test coverage exists or has been added/updated - [x] tested in a private testnet # Breaking changes - [x] I have checked my code for breaking changes - [x] If there are breaking changes, there is a supporting migration.
1 parent d3bc02e commit 4ff05b3

30 files changed

+2504
-142
lines changed

app/app.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,7 @@ func New(
650650
app.BankKeeper,
651651
app.AccountKeeper,
652652
app.SchedulerKeeper,
653+
app.EvmKeeper,
653654
)
654655

655656
app.ScopedConsensusKeeper = scopedConsensusKeeper

proto/palomachain/paloma/treasury/fees.proto

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,48 @@ import "gogoproto/gogo.proto";
55
import "google/api/annotations.proto";
66
import "cosmos/base/query/v1beta1/pagination.proto";
77
import "palomachain/paloma/treasury/params.proto";
8+
import "cosmos_proto/cosmos.proto";
9+
import "amino/amino.proto";
810

911
option go_package = "github.com/palomachain/paloma/x/treasury/types";
1012

13+
// Empty represents an empty message
14+
message Empty {}
15+
1116
message Fees {
1217
string communityFundFee = 1;
1318
string securityFee = 2;
1419
}
20+
21+
// Represents the fee setting of an individual relayer for a target chain.
22+
message RelayerFeeSetting {
23+
option (gogoproto.equal) = true;
24+
option (gogoproto.goproto_stringer) = true;
25+
26+
message FeeSetting {
27+
option (gogoproto.equal) = true;
28+
option (gogoproto.goproto_stringer) = true;
29+
// Describes the factor by which the gas spent on a
30+
// relayed transaction will be reimbursed.
31+
// e.g. `1.2` -> relayer asks to be reimbursed with `total_gas_cost * 1.2`
32+
// lower fee settings prioritize the relayer higher in the
33+
// pool.
34+
// A value below 1 indicates likely partial loss of funds.
35+
// `0` means no fees, with a total loss of funds.
36+
// Negative values are rejected.
37+
string multiplicator = 1 [
38+
(cosmos_proto.scalar) = "cosmos.Dec",
39+
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
40+
(amino.dont_omitempty) = true,
41+
(gogoproto.nullable) = false
42+
];
43+
44+
// Indicates the reference ID of the target chain.
45+
string chain_reference_id = 2;
46+
}
47+
48+
// Validator address of a validator participating in consensus.
49+
string val_address = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];
50+
51+
repeated FeeSetting fees = 2 [(gogoproto.nullable) = false];
52+
}

proto/palomachain/paloma/treasury/genesis.proto

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ option go_package = "github.com/palomachain/paloma/x/treasury/types";
1010
// GenesisState defines the treasury module's genesis state.
1111
message GenesisState {
1212
Params params = 1 [ (gogoproto.nullable) = false ];
13-
Fees treasuryFees = 2;
13+
Fees treasuryFees = 2[ (gogoproto.nullable) = false ];
14+
repeated RelayerFeeSetting relayer_fee_settings = 3[ (gogoproto.nullable) = false ];
1415
}

proto/palomachain/paloma/treasury/query.proto

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ package palomachain.paloma.treasury;
44
import "gogoproto/gogo.proto";
55
import "google/api/annotations.proto";
66
import "cosmos/base/query/v1beta1/pagination.proto";
7+
import "cosmos_proto/cosmos.proto";
8+
79
import "palomachain/paloma/treasury/params.proto";
810
import "palomachain/paloma/treasury/fees.proto";
911

@@ -19,6 +21,11 @@ service Query {
1921
rpc QueryFees(QueryFeesRequest) returns (Fees) {
2022
option (google.api.http).get = "/palomachain/paloma/treasury/fees";
2123
}
24+
25+
// RelayerFee queries the fee settings of a validator participating in consensus.
26+
rpc RelayerFee(QueryRelayerFeeRequest) returns (RelayerFeeSetting) {
27+
option (google.api.http).get = "/palomachain/paloma/treasury/relayer_fee";
28+
}
2229
}
2330

2431
// QueryParamsRequest is request type for the Query/Params RPC method.
@@ -31,3 +38,11 @@ message QueryParamsResponse {
3138
}
3239

3340
message QueryFeesRequest {}
41+
42+
// QueryRelayerFeeRequest is the request type for the Query/RelayerFee RPC method.
43+
message QueryRelayerFeeRequest {
44+
// val_address holds the validator address of the validator you want to query
45+
// for.
46+
string val_address = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];
47+
}
48+
Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,25 @@
11
syntax = "proto3";
22
package palomachain.paloma.treasury;
33

4+
import "gogoproto/gogo.proto";
5+
import "cosmos/msg/v1/msg.proto";
6+
7+
import "palomachain/paloma/valset/common.proto";
8+
import "palomachain/paloma/treasury/fees.proto";
9+
410
option go_package = "github.com/palomachain/paloma/x/treasury/types";
511

612
// Msg defines the Msg service.
7-
service Msg {}
13+
service Msg {
14+
rpc UpsertRelayerFee(MsgUpsertRelayerFee)
15+
returns (Empty);
16+
}
17+
18+
message MsgUpsertRelayerFee {
19+
option (cosmos.msg.v1.signer) = "metadata";
20+
21+
palomachain.paloma.valset.MsgMetadata metadata = 1
22+
[ (gogoproto.nullable) = false ];
23+
24+
RelayerFeeSetting fee_setting = 2;
25+
}

testutil/keeper/treasury.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ func TreasuryKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
4545
nil,
4646
nil,
4747
nil,
48+
nil,
4849
)
4950

5051
ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger())

util/keeper/mocks/KVStoreWrapper.go

Lines changed: 96 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

util/keeper/wrapper.go

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,54 @@
11
package keeper
22

33
import (
4-
"github.com/cosmos/cosmos-sdk/codec"
4+
"context"
5+
6+
corestore "cosmossdk.io/core/store"
7+
"cosmossdk.io/store/prefix"
8+
storetypes "cosmossdk.io/store/types"
9+
"github.com/cosmos/cosmos-sdk/runtime"
510
"github.com/cosmos/cosmos-sdk/types"
11+
"github.com/cosmos/gogoproto/proto"
612
)
713

814
type Byter interface {
915
Bytes() []byte
1016
}
1117

12-
func NewKvStoreWrapper[T codec.ProtoMarshaler](s StoreGetterFn, ps ProtoSerializer) *KVStoreWrapper[T] {
13-
return &KVStoreWrapper[T]{
18+
func NewKvStoreWrapper[T proto.Message](s StoreGetterFn, ps ProtoSerializer) *kvStoreWrapper[T] {
19+
return &kvStoreWrapper[T]{
1420
sg: s,
1521
ps: ps,
1622
}
1723
}
1824

19-
type KVStoreWrapper[T codec.ProtoMarshaler] struct {
25+
//go:generate mockery --name=KVStoreWrapper
26+
type KVStoreWrapper[T proto.Message] interface {
27+
Get(ctx types.Context, key Byter) (T, error)
28+
Set(ctx types.Context, key Byter, value T) error
29+
Iterate(ctx types.Context, fn func([]byte, T) bool) error
30+
}
31+
32+
type kvStoreWrapper[T proto.Message] struct {
2033
sg StoreGetterFn
2134
ps ProtoSerializer
2235
}
2336

24-
func (v *KVStoreWrapper[T]) Get(ctx types.Context, key Byter) (T, error) {
37+
func (v *kvStoreWrapper[T]) Get(ctx types.Context, key Byter) (T, error) {
2538
return Load[T](v.sg(ctx), v.ps, key.Bytes())
2639
}
2740

28-
func (v *KVStoreWrapper[T]) Set(ctx types.Context, key Byter, value T) error {
41+
func (v *kvStoreWrapper[T]) Set(ctx types.Context, key Byter, value T) error {
2942
return Save(v.sg(ctx), v.ps, key.Bytes(), value)
3043
}
3144

32-
func (v *KVStoreWrapper[T]) Iterate(ctx types.Context, fn func([]byte, T) bool) error {
33-
return IterAllFnc[T](v.sg(ctx), v.ps, fn)
45+
func (v *kvStoreWrapper[T]) Iterate(ctx types.Context, fn func([]byte, T) bool) error {
46+
return IterAllFnc(v.sg(ctx), v.ps, fn)
47+
}
48+
49+
func StoreFactory(storeKey corestore.KVStoreService, p string) func(ctx context.Context) storetypes.KVStore {
50+
return func(ctx context.Context) storetypes.KVStore {
51+
s := runtime.KVStoreAdapter(storeKey.OpenKVStore(ctx))
52+
return prefix.NewStore(s, []byte(p))
53+
}
3454
}

x/metrix/keeper/keeper.go

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,12 @@ import (
1111
corestore "cosmossdk.io/core/store"
1212
"cosmossdk.io/log"
1313
"cosmossdk.io/math"
14-
"cosmossdk.io/store/prefix"
15-
storetypes "cosmossdk.io/store/types"
1614
"github.com/cosmos/cosmos-sdk/codec"
17-
"github.com/cosmos/cosmos-sdk/runtime"
1815
sdk "github.com/cosmos/cosmos-sdk/types"
1916
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
2017
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
2118
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
19+
"github.com/cosmos/gogoproto/proto"
2220
keeperutil "github.com/palomachain/paloma/util/keeper"
2321
"github.com/palomachain/paloma/util/liblog"
2422
"github.com/palomachain/paloma/util/palomath"
@@ -56,9 +54,9 @@ type (
5654
slashing types.SlashingKeeper
5755
staking types.StakingKeeper
5856

59-
metrics *keeperutil.KVStoreWrapper[*types.ValidatorMetrics]
60-
history *keeperutil.KVStoreWrapper[*types.ValidatorHistory]
61-
messageNonceCache *keeperutil.KVStoreWrapper[*types.HistoricRelayData]
57+
metrics keeperutil.KVStoreWrapper[*types.ValidatorMetrics]
58+
history keeperutil.KVStoreWrapper[*types.ValidatorHistory]
59+
messageNonceCache keeperutil.KVStoreWrapper[*types.HistoricRelayData]
6260
AddressCodec address.Codec
6361
}
6462
)
@@ -81,9 +79,9 @@ func NewKeeper(
8179
paramstore: ps,
8280
slashing: slashing,
8381
staking: staking,
84-
metrics: keeperutil.NewKvStoreWrapper[*types.ValidatorMetrics](storeFactory(storeKey, types.MetricsStorePrefix), cdc),
85-
history: keeperutil.NewKvStoreWrapper[*types.ValidatorHistory](storeFactory(storeKey, types.HistoryStorePrefix), cdc),
86-
messageNonceCache: keeperutil.NewKvStoreWrapper[*types.HistoricRelayData](storeFactory(storeKey, types.MessageNonceCacheStorePrefix), cdc),
82+
metrics: keeperutil.NewKvStoreWrapper[*types.ValidatorMetrics](keeperutil.StoreFactory(storeKey, types.MetricsStorePrefix), cdc),
83+
history: keeperutil.NewKvStoreWrapper[*types.ValidatorHistory](keeperutil.StoreFactory(storeKey, types.HistoryStorePrefix), cdc),
84+
messageNonceCache: keeperutil.NewKvStoreWrapper[*types.HistoricRelayData](keeperutil.StoreFactory(storeKey, types.MessageNonceCacheStorePrefix), cdc),
8785
AddressCodec: addressCodec,
8886
}
8987
}
@@ -478,13 +476,6 @@ func (k Keeper) tryUpdateRecord(ctx context.Context, valAddr sdk.ValAddress, pat
478476
return nil
479477
}
480478

481-
func storeFactory(storeKey corestore.KVStoreService, p string) func(ctx context.Context) storetypes.KVStore {
482-
return func(ctx context.Context) storetypes.KVStore {
483-
s := runtime.KVStoreAdapter(storeKey.OpenKVStore(ctx))
484-
return prefix.NewStore(s, types.KeyPrefix(p))
485-
}
486-
}
487-
488479
func calculateUptime(window, missed int64) math.LegacyDec {
489480
if window < 1 || missed < 0 || missed > window {
490481
return math.LegacyNewDec(0)
@@ -498,7 +489,7 @@ func calculateUptime(window, missed int64) math.LegacyDec {
498489
return palomath.BigIntDiv(diff, w)
499490
}
500491

501-
func getFromStore[T codec.ProtoMarshaler](ctx context.Context, store *keeperutil.KVStoreWrapper[T], key keeperutil.Byter) (T, error) {
492+
func getFromStore[T proto.Message](ctx context.Context, store keeperutil.KVStoreWrapper[T], key keeperutil.Byter) (T, error) {
502493
var empty T
503494
sdkCtx := sdk.UnwrapSDKContext(ctx)
504495
data, err := store.Get(sdkCtx, key)

x/metrix/types/keys.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,3 @@ func (m CacheKey) Bytes() []byte { return []byte(m) }
3636
type Key []byte
3737

3838
func (k Key) Bytes() []byte { return k }
39-
40-
func KeyPrefix(p string) []byte {
41-
return []byte(p)
42-
}

x/treasury/client/cli/query.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ func GetQueryCmd(queryRoute string) *cobra.Command {
2121

2222
cmd.AddCommand(CmdQueryParams())
2323
cmd.AddCommand(CmdGetFees())
24+
cmd.AddCommand(CmdGetRelayerFee())
2425

2526
return cmd
2627
}

0 commit comments

Comments
 (0)