@@ -28,6 +28,7 @@ import (
2828const (
2929 AppVersionV5 uint64 = 5
3030 AppVersionV6 uint64 = 6
31+ AppVersionV7 uint64 = 7
3132
3233 InflationRateV5 = "0.0536" // 5.36%
3334 InflationRateV6 = "0.0267" // 2.67%
@@ -37,6 +38,9 @@ const (
3738
3839 MinCommissionRateV5 = "0.05" // 5%
3940 MinCommissionRateV6 = "0.10" // 10%
41+ MinCommissionRateV7 = "0.20" // 20%
42+
43+ MaxCommissionRateV7 = "0.60" // 60%
4044
4145 EvidenceMaxAgeV5Hours = 504
4246 EvidenceMaxAgeV6Hours = 337
@@ -76,6 +80,10 @@ func (s *CelestiaTestSuite) TestAllUpgrades() {
7680 baseAppVersion : 5 ,
7781 targetAppVersion : 6 ,
7882 },
83+ {
84+ baseAppVersion : 6 ,
85+ targetAppVersion : 7 ,
86+ },
7987 }
8088
8189 for _ , tc := range tt {
@@ -386,6 +394,12 @@ func (s *CelestiaTestSuite) validateParameters(ctx context.Context, node tastora
386394 return
387395 }
388396
397+ if appVersion == AppVersionV7 {
398+ s .validateMinCommissionRate (ctx , node , MinCommissionRateV7 , AppVersionV7 )
399+ s .validateMaxCommissionRate (ctx , node , MaxCommissionRateV7 , AppVersionV7 )
400+ return
401+ }
402+
389403 s .T ().Fatalf ("invalid app version: %d" , appVersion )
390404}
391405
@@ -485,6 +499,48 @@ func (s *CelestiaTestSuite) validateMinCommissionRate(ctx context.Context, node
485499 s .Require ().True (diff .LTE (tolerance ), "v%d min commission rate mismatch: expected %s, got %s, diff=%s" , appVersion , expectedRate , minCommissionRateStr , diff .String ())
486500}
487501
502+ // validateMaxCommissionRate queries all validators and validates that each
503+ // validator's max commission rate is at least the expected value.
504+ func (s * CelestiaTestSuite ) validateMaxCommissionRate (ctx context.Context , node tastoratypes.ChainNode , expectedRate string , appVersion uint64 ) {
505+ dcNode , ok := node .(* tastoradockertypes.ChainNode )
506+ s .Require ().True (ok , "node should be a docker chain node" )
507+
508+ networkInfo , err := node .GetNetworkInfo (ctx )
509+ s .Require ().NoError (err , "failed to get network info from chain node" )
510+
511+ rpcEndpoint := fmt .Sprintf ("tcp://%s:26657" , networkInfo .Internal .Hostname )
512+ cmd := []string {"celestia-appd" , "query" , "staking" , "validators" , "--output" , "json" , "--node" , rpcEndpoint }
513+
514+ stdout , stderr , err := dcNode .Exec (ctx , cmd , nil )
515+ s .Require ().NoError (err , "failed to query staking validators via CLI: stderr=%s" , string (stderr ))
516+
517+ var validatorsResp struct {
518+ Validators []struct {
519+ Commission struct {
520+ CommissionRates struct {
521+ MaxRate string `json:"max_rate"`
522+ } `json:"commission_rates"`
523+ } `json:"commission"`
524+ } `json:"validators"`
525+ }
526+ err = json .Unmarshal (stdout , & validatorsResp )
527+ s .Require ().NoError (err , "failed to parse staking validators JSON response" )
528+ s .Require ().NotEmpty (validatorsResp .Validators , "no validators found in response" )
529+
530+ expectedDec , err := math .LegacyNewDecFromStr (expectedRate )
531+ s .Require ().NoError (err , "failed to parse expected max commission rate" )
532+
533+ for i , val := range validatorsResp .Validators {
534+ maxRateStr := val .Commission .CommissionRates .MaxRate
535+ s .Require ().NotEmpty (maxRateStr , "max_rate not found for validator %d" , i )
536+
537+ actualDec , err := math .LegacyNewDecFromStr (maxRateStr )
538+ s .Require ().NoError (err , "failed to parse actual max commission rate for validator %d: %s" , i , maxRateStr )
539+
540+ s .Require ().True (actualDec .GTE (expectedDec ), "v%d validator %d max commission rate too low: expected >= %s, got %s" , appVersion , i , expectedRate , maxRateStr )
541+ }
542+ }
543+
488544// validateEvidenceParams queries and validates both evidence max age duration and blocks using CLI
489545func (s * CelestiaTestSuite ) validateEvidenceParams (ctx context.Context , node tastoratypes.ChainNode , expectedHours int , expectedBlocks int , appVersion uint64 ) {
490546 dcNode , ok := node .(* tastoradockertypes.ChainNode )
0 commit comments