github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/staking/types/commission.go (about) 1 package types 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/tendermint/go-amino" 8 9 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 10 ) 11 12 type ( 13 // Commission defines a commission parameters for a given validator 14 Commission struct { 15 CommissionRates `json:"commission_rates" yaml:"commission_rates"` 16 UpdateTime time.Time `json:"update_time" yaml:"update_time"` // the last time the commission rate was changed 17 } 18 19 // CommissionRates defines the initial commission rates to be used for creating a validator 20 CommissionRates struct { 21 // the commission rate charged to delegators, as a fraction 22 Rate sdk.Dec `json:"rate" yaml:"rate"` 23 // maximum commission rate which validator can ever charge, as a fraction 24 MaxRate sdk.Dec `json:"max_rate" yaml:"max_rate"` 25 // maximum daily increase of the validator commission, as a fraction 26 MaxChangeRate sdk.Dec `json:"max_change_rate" yaml:"max_change_rate"` 27 } 28 ) 29 30 // NewCommissionRates returns an initialized validator commission rates 31 func NewCommissionRates(rate, maxRate, maxChangeRate sdk.Dec) CommissionRates { 32 return CommissionRates{ 33 Rate: rate, 34 MaxRate: maxRate, 35 MaxChangeRate: maxChangeRate, 36 } 37 } 38 39 // NewCommission returns an initialized validator commission. 40 func NewCommission(rate, maxRate, maxChangeRate sdk.Dec) Commission { 41 return Commission{ 42 CommissionRates: NewCommissionRates(rate, maxRate, maxChangeRate), 43 UpdateTime: time.Unix(0, 0).UTC(), 44 } 45 } 46 47 // NewCommissionWithTime returns an initialized validator commission with a specified update time which should be the 48 // current block BFT time 49 func NewCommissionWithTime(rate, maxRate, maxChangeRate sdk.Dec, updatedAt time.Time) Commission { 50 return Commission{ 51 CommissionRates: NewCommissionRates(rate, maxRate, maxChangeRate), 52 UpdateTime: updatedAt, 53 } 54 } 55 56 // Equal checks if the given Commission object is equal to the receiving Commission object 57 func (c Commission) Equal(c2 Commission) bool { 58 return c.Rate.Equal(c2.Rate) && 59 c.MaxRate.Equal(c2.MaxRate) && 60 c.MaxChangeRate.Equal(c2.MaxChangeRate) && 61 c.UpdateTime.Equal(c2.UpdateTime) 62 } 63 64 // String implements the Stringer interface for a Commission 65 func (c Commission) String() string { 66 return fmt.Sprintf("rate: %s, maxRate: %s, maxChangeRate: %s, updateTime: %s", 67 c.Rate, c.MaxRate, c.MaxChangeRate, c.UpdateTime, 68 ) 69 } 70 71 func (c *Commission) UnmarshalFromAmino(cdc *amino.Codec, data []byte) error { 72 var dataLen uint64 = 0 73 var subData []byte 74 var timeUpdated bool 75 76 for { 77 data = data[dataLen:] 78 79 if len(data) == 0 { 80 break 81 } 82 83 pos, pbType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 84 if err != nil { 85 return err 86 } 87 data = data[1:] 88 89 if pbType != amino.Typ3_ByteLength { 90 return fmt.Errorf("Commission : all fields type should be 2") 91 } 92 93 var n int 94 dataLen, n, err = amino.DecodeUvarint(data) 95 if err != nil { 96 return err 97 } 98 data = data[n:] 99 if len(data) < int(dataLen) { 100 return fmt.Errorf("invalid data len") 101 } 102 subData = data[:dataLen] 103 104 switch pos { 105 case 1: 106 if err = c.CommissionRates.UnmarshalFromAmino(cdc, subData); err != nil { 107 return err 108 } 109 case 2: 110 c.UpdateTime, _, err = amino.DecodeTime(subData) 111 if err != nil { 112 return err 113 } 114 timeUpdated = true 115 default: 116 return fmt.Errorf("unexpect feild num %d", pos) 117 } 118 } 119 if !timeUpdated { 120 c.UpdateTime = amino.ZeroTime 121 } 122 return nil 123 } 124 125 // Validate performs basic sanity validation checks of initial commission parameters 126 // If validation fails, an SDK error is returned 127 func (c CommissionRates) Validate() sdk.Error { 128 switch { 129 case c.MaxRate.LT(sdk.ZeroDec()): 130 // max rate cannot be negative 131 return ErrCommissionNegative() 132 133 case c.MaxRate.GT(sdk.OneDec()): 134 // max rate cannot be greater than 1 135 return ErrCommissionHuge() 136 137 case c.Rate.LT(sdk.ZeroDec()): 138 // rate cannot be negative 139 return ErrCommissionNegative() 140 141 case c.Rate.GT(c.MaxRate): 142 // rate cannot be greater than the max rate 143 return ErrCommissionGTMaxRate() 144 145 case c.MaxChangeRate.LT(sdk.ZeroDec()): 146 // change rate cannot be negative 147 return ErrCommissionChangeRateNegative() 148 149 case c.MaxChangeRate.GT(c.MaxRate): 150 // change rate cannot be greater than the max rate 151 return ErrCommissionChangeRateGTMaxRate() 152 } 153 154 return nil 155 } 156 157 // ValidateNewRate performs basic sanity validation checks of a new commission rate 158 // If validation fails, an SDK error is returned. 159 func (c Commission) ValidateNewRate(newRate sdk.Dec, blockTime time.Time) sdk.Error { 160 switch { 161 case blockTime.Sub(c.UpdateTime).Hours() < DefaultValidateRateUpdateInterval: 162 // new rate cannot be changed more than once within 24 hours 163 return ErrCommissionUpdateTime() 164 165 case newRate.LT(sdk.ZeroDec()): 166 // new rate cannot be negative 167 return ErrCommissionNegative() 168 169 case newRate.GT(c.MaxRate): 170 // new rate cannot be greater than the max rate 171 return ErrCommissionGTMaxRate() 172 173 //MaxChangeRate is 0,ignore it 174 //case newRate.Sub(c.Rate).GT(c.MaxChangeRate): 175 // // new rate % points change cannot be greater than the max change rate 176 // return ErrCommissionGTMaxChangeRate() 177 } 178 179 return nil 180 } 181 182 func (c *CommissionRates) UnmarshalFromAmino(cdc *amino.Codec, data []byte) error { 183 var dataLen uint64 = 0 184 var subData []byte 185 186 for { 187 data = data[dataLen:] 188 189 if len(data) == 0 { 190 break 191 } 192 193 pos, pbType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 194 if err != nil { 195 return err 196 } 197 data = data[1:] 198 199 if pbType != amino.Typ3_ByteLength { 200 return fmt.Errorf("CommissionRatestype : all fields type should be 2") 201 } 202 203 var n int 204 dataLen, n, err = amino.DecodeUvarint(data) 205 if err != nil { 206 return err 207 } 208 data = data[n:] 209 if len(data) < int(dataLen) { 210 return fmt.Errorf("invalid data len") 211 } 212 subData = data[:dataLen] 213 214 switch pos { 215 case 1: 216 if err = c.Rate.UnmarshalFromAmino(cdc, subData); err != nil { 217 return err 218 } 219 case 2: 220 if err = c.MaxRate.UnmarshalFromAmino(cdc, subData); err != nil { 221 return err 222 } 223 case 3: 224 if err = c.MaxChangeRate.UnmarshalFromAmino(cdc, subData); err != nil { 225 return err 226 } 227 default: 228 return fmt.Errorf("unexpect feild num %d", pos) 229 } 230 } 231 return nil 232 }