github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evm/types/proposal.go (about) 1 package types 2 3 import ( 4 "fmt" 5 "strings" 6 7 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 8 "github.com/fibonacci-chain/fbc/libs/tendermint/global" 9 "github.com/fibonacci-chain/fbc/libs/tendermint/types" 10 govtypes "github.com/fibonacci-chain/fbc/x/gov/types" 11 ) 12 13 const ( 14 maxAddressListLength = 100 15 // proposalTypeManageContractDeploymentWhitelist defines the type for a ManageContractDeploymentWhitelist 16 proposalTypeManageContractDeploymentWhitelist = "ManageContractDeploymentWhitelist" 17 // proposalTypeManageContractBlockedList defines the type for a ManageContractBlockedListProposal 18 proposalTypeManageContractBlockedList = "ManageContractBlockedList" 19 // proposalTypeManageContractMethodBlockedList defines the type for a ManageContractMethodBlockedList 20 proposalTypeManageContractMethodBlockedList = "ManageContractMethodBlockedList" 21 // proposalTypeManageSysContractAddress defines the type for a ManageSysContractAddress 22 proposalTypeManageSysContractAddress = "ManageSysContractAddress" 23 proposalTypeManageContractByteCode = "ManageContractByteCode" 24 ) 25 26 func init() { 27 govtypes.RegisterProposalType(proposalTypeManageContractDeploymentWhitelist) 28 govtypes.RegisterProposalType(proposalTypeManageContractBlockedList) 29 govtypes.RegisterProposalType(proposalTypeManageContractMethodBlockedList) 30 govtypes.RegisterProposalType(proposalTypeManageSysContractAddress) 31 govtypes.RegisterProposalType(proposalTypeManageContractByteCode) 32 33 govtypes.RegisterProposalTypeCodec(ManageContractDeploymentWhitelistProposal{}, "fbexchain/evm/ManageContractDeploymentWhitelistProposal") 34 govtypes.RegisterProposalTypeCodec(ManageContractBlockedListProposal{}, "fbexchain/evm/ManageContractBlockedListProposal") 35 govtypes.RegisterProposalTypeCodec(ManageContractMethodBlockedListProposal{}, "fbexchain/evm/ManageContractMethodBlockedListProposal") 36 govtypes.RegisterProposalTypeCodec(ManageSysContractAddressProposal{}, "fbexchain/evm/ManageSysContractAddressProposal") 37 govtypes.RegisterProposalTypeCodec(ManageContractByteCodeProposal{}, "fbexchain/evm/ManageContractBytecode") 38 39 } 40 41 var ( 42 _ govtypes.Content = (*ManageContractDeploymentWhitelistProposal)(nil) 43 _ govtypes.Content = (*ManageContractBlockedListProposal)(nil) 44 _ govtypes.Content = (*ManageContractMethodBlockedListProposal)(nil) 45 _ govtypes.Content = (*ManageSysContractAddressProposal)(nil) 46 _ govtypes.Content = (*ManageContractByteCodeProposal)(nil) 47 ) 48 49 // ManageContractDeploymentWhitelistProposal - structure for the proposal to add or delete deployer addresses from whitelist 50 type ManageContractDeploymentWhitelistProposal struct { 51 Title string `json:"title" yaml:"title"` 52 Description string `json:"description" yaml:"description"` 53 DistributorAddrs AddressList `json:"distributor_addresses" yaml:"distributor_addresses"` 54 IsAdded bool `json:"is_added" yaml:"is_added"` 55 } 56 57 // NewManageContractDeploymentWhitelistProposal creates a new instance of ManageContractDeploymentWhitelistProposal 58 func NewManageContractDeploymentWhitelistProposal(title, description string, distributorAddrs []sdk.AccAddress, isAdded bool, 59 ) ManageContractDeploymentWhitelistProposal { 60 return ManageContractDeploymentWhitelistProposal{ 61 Title: title, 62 Description: description, 63 DistributorAddrs: distributorAddrs, 64 IsAdded: isAdded, 65 } 66 } 67 68 // GetTitle returns title of a manage contract deployment whitelist proposal object 69 func (mp ManageContractDeploymentWhitelistProposal) GetTitle() string { 70 return mp.Title 71 } 72 73 // GetDescription returns description of a manage contract deployment whitelist proposal object 74 func (mp ManageContractDeploymentWhitelistProposal) GetDescription() string { 75 return mp.Description 76 } 77 78 // ProposalRoute returns route key of a manage contract deployment whitelist proposal object 79 func (mp ManageContractDeploymentWhitelistProposal) ProposalRoute() string { 80 return RouterKey 81 } 82 83 // ProposalType returns type of a manage contract deployment whitelist proposal object 84 func (mp ManageContractDeploymentWhitelistProposal) ProposalType() string { 85 return proposalTypeManageContractDeploymentWhitelist 86 } 87 88 // ValidateBasic validates a manage contract deployment whitelist proposal 89 func (mp ManageContractDeploymentWhitelistProposal) ValidateBasic() sdk.Error { 90 if len(strings.TrimSpace(mp.Title)) == 0 { 91 return govtypes.ErrInvalidProposalContent("title is required") 92 } 93 if len(mp.Title) > govtypes.MaxTitleLength { 94 return govtypes.ErrInvalidProposalContent("title length is longer than the maximum title length") 95 } 96 97 if len(mp.Description) == 0 { 98 return govtypes.ErrInvalidProposalContent("description is required") 99 } 100 101 if len(mp.Description) > govtypes.MaxDescriptionLength { 102 return govtypes.ErrInvalidProposalContent("description length is longer than the maximum description length") 103 } 104 105 if mp.ProposalType() != proposalTypeManageContractDeploymentWhitelist { 106 return govtypes.ErrInvalidProposalType(mp.ProposalType()) 107 } 108 109 distributorAddrLen := len(mp.DistributorAddrs) 110 if distributorAddrLen == 0 { 111 return ErrEmptyAddressList 112 } 113 114 if distributorAddrLen > maxAddressListLength { 115 return ErrOversizeAddrList(distributorAddrLen) 116 } 117 118 if isAddrDuplicated(mp.DistributorAddrs) { 119 return ErrDuplicatedAddr 120 } 121 122 return nil 123 } 124 125 // String returns a human readable string representation of a ManageContractDeploymentWhitelistProposal 126 func (mp ManageContractDeploymentWhitelistProposal) String() string { 127 var builder strings.Builder 128 builder.WriteString( 129 fmt.Sprintf(`ManageContractDeploymentWhitelistProposal: 130 Title: %s 131 Description: %s 132 Type: %s 133 IsAdded: %t 134 DistributorAddrs: 135 `, 136 mp.Title, mp.Description, mp.ProposalType(), mp.IsAdded), 137 ) 138 139 for i := 0; i < len(mp.DistributorAddrs); i++ { 140 builder.WriteString("\t\t\t\t\t\t") 141 builder.WriteString(mp.DistributorAddrs[i].String()) 142 builder.Write([]byte{'\n'}) 143 } 144 145 return strings.TrimSpace(builder.String()) 146 } 147 148 func isAddrDuplicated(addrs []sdk.AccAddress) bool { 149 lenAddrs := len(addrs) 150 filter := make(map[string]struct{}, lenAddrs) 151 for i := 0; i < lenAddrs; i++ { 152 key := addrs[i].String() 153 if _, ok := filter[key]; ok { 154 return true 155 } 156 filter[key] = struct{}{} 157 } 158 159 return false 160 } 161 162 // ManageContractBlockedListProposal - structure for the proposal to add or delete a contract address from blocked list 163 type ManageContractBlockedListProposal struct { 164 Title string `json:"title" yaml:"title"` 165 Description string `json:"description" yaml:"description"` 166 ContractAddrs AddressList `json:"contract_addresses" yaml:"contract_addresses"` 167 IsAdded bool `json:"is_added" yaml:"is_added"` 168 } 169 170 // NewManageContractBlockedListProposal creates a new instance of ManageContractBlockedListProposal 171 func NewManageContractBlockedListProposal(title, description string, contractAddrs AddressList, isAdded bool, 172 ) ManageContractBlockedListProposal { 173 return ManageContractBlockedListProposal{ 174 Title: title, 175 Description: description, 176 ContractAddrs: contractAddrs, 177 IsAdded: isAdded, 178 } 179 } 180 181 // GetTitle returns title of a manage contract blocked list proposal object 182 func (mp ManageContractBlockedListProposal) GetTitle() string { 183 return mp.Title 184 } 185 186 // GetDescription returns description of a manage contract blocked list proposal object 187 func (mp ManageContractBlockedListProposal) GetDescription() string { 188 return mp.Description 189 } 190 191 // ProposalRoute returns route key of a manage contract blocked list proposal object 192 func (mp ManageContractBlockedListProposal) ProposalRoute() string { 193 return RouterKey 194 } 195 196 // ProposalType returns type of a manage contract blocked list proposal object 197 func (mp ManageContractBlockedListProposal) ProposalType() string { 198 return proposalTypeManageContractBlockedList 199 } 200 201 // ValidateBasic validates a manage contract blocked list proposal 202 func (mp ManageContractBlockedListProposal) ValidateBasic() sdk.Error { 203 if len(strings.TrimSpace(mp.Title)) == 0 { 204 return govtypes.ErrInvalidProposalContent("title is required") 205 } 206 if len(mp.Title) > govtypes.MaxTitleLength { 207 return govtypes.ErrInvalidProposalContent("title length is longer than the maximum title length") 208 } 209 210 if len(mp.Description) == 0 { 211 return govtypes.ErrInvalidProposalContent("description is required") 212 } 213 214 if len(mp.Description) > govtypes.MaxDescriptionLength { 215 return govtypes.ErrInvalidProposalContent("description length is longer than the maximum description length") 216 } 217 218 if mp.ProposalType() != proposalTypeManageContractBlockedList { 219 return govtypes.ErrInvalidProposalType(mp.ProposalType()) 220 } 221 222 contractAddrLen := len(mp.ContractAddrs) 223 if contractAddrLen == 0 { 224 return ErrEmptyAddressList 225 } 226 227 if contractAddrLen > maxAddressListLength { 228 return ErrOversizeAddrList(contractAddrLen) 229 } 230 231 if isAddrDuplicated(mp.ContractAddrs) { 232 return ErrDuplicatedAddr 233 } 234 235 return nil 236 } 237 238 // String returns a human readable string representation of a ManageContractBlockedListProposal 239 func (mp ManageContractBlockedListProposal) String() string { 240 var builder strings.Builder 241 builder.WriteString( 242 fmt.Sprintf(`ManageContractBlockedListProposal: 243 Title: %s 244 Description: %s 245 Type: %s 246 IsAdded: %t 247 ContractAddrs: 248 `, 249 mp.Title, mp.Description, mp.ProposalType(), mp.IsAdded), 250 ) 251 252 for i := 0; i < len(mp.ContractAddrs); i++ { 253 builder.WriteString("\t\t\t\t\t\t") 254 builder.WriteString(mp.ContractAddrs[i].String()) 255 builder.Write([]byte{'\n'}) 256 } 257 258 return strings.TrimSpace(builder.String()) 259 } 260 261 // ManageContractMethodBlockedListProposal - structure for the proposal to add or delete a contract method from blocked list 262 type ManageContractMethodBlockedListProposal struct { 263 Title string `json:"title" yaml:"title"` 264 Description string `json:"description" yaml:"description"` 265 ContractList BlockedContractList `json:"contract_addresses" yaml:"contract_addresses"` 266 IsAdded bool `json:"is_added" yaml:"is_added"` 267 } 268 269 // NewManageContractMethodBlockedListProposal creates a new instance of ManageContractMethodBlockedListProposal 270 func NewManageContractMethodBlockedListProposal(title, description string, contractList BlockedContractList, isAdded bool, 271 ) ManageContractMethodBlockedListProposal { 272 return ManageContractMethodBlockedListProposal{ 273 Title: title, 274 Description: description, 275 ContractList: contractList, 276 IsAdded: isAdded, 277 } 278 } 279 280 // GetTitle returns title of a manage contract blocked list proposal object 281 func (mp ManageContractMethodBlockedListProposal) GetTitle() string { 282 return mp.Title 283 } 284 285 // GetDescription returns description of a manage contract blocked list proposal object 286 func (mp ManageContractMethodBlockedListProposal) GetDescription() string { 287 return mp.Description 288 } 289 290 // ProposalRoute returns route key of a manage contract blocked list proposal object 291 func (mp ManageContractMethodBlockedListProposal) ProposalRoute() string { 292 return RouterKey 293 } 294 295 // ProposalType returns type of a manage contract blocked list proposal object 296 func (mp ManageContractMethodBlockedListProposal) ProposalType() string { 297 return proposalTypeManageContractMethodBlockedList 298 } 299 300 // ValidateBasic validates a manage contract blocked list proposal 301 func (mp ManageContractMethodBlockedListProposal) ValidateBasic() sdk.Error { 302 if len(strings.TrimSpace(mp.Title)) == 0 { 303 return govtypes.ErrInvalidProposalContent("title is required") 304 } 305 if len(mp.Title) > govtypes.MaxTitleLength { 306 return govtypes.ErrInvalidProposalContent("title length is longer than the maximum title length") 307 } 308 309 if len(mp.Description) == 0 { 310 return govtypes.ErrInvalidProposalContent("description is required") 311 } 312 313 if len(mp.Description) > govtypes.MaxDescriptionLength { 314 return govtypes.ErrInvalidProposalContent("description length is longer than the maximum description length") 315 } 316 317 if mp.ProposalType() != proposalTypeManageContractMethodBlockedList { 318 return govtypes.ErrInvalidProposalType(mp.ProposalType()) 319 } 320 321 contractAddrLen := len(mp.ContractList) 322 if contractAddrLen == 0 { 323 return ErrEmptyAddressList 324 } 325 326 if contractAddrLen > maxAddressListLength { 327 return ErrOversizeAddrList(contractAddrLen) 328 } 329 330 if err := mp.ContractList.ValidateBasic(); err != nil { 331 return err 332 } 333 334 return nil 335 } 336 337 // String returns a human readable string representation of a ManageContractMethodBlockedListProposal 338 func (mp ManageContractMethodBlockedListProposal) String() string { 339 var builder strings.Builder 340 builder.WriteString( 341 fmt.Sprintf(`ManageContractMethodBlockedListProposal: 342 Title: %s 343 Description: %s 344 Type: %s 345 IsAdded: %t 346 ContractList: 347 `, 348 mp.Title, mp.Description, mp.ProposalType(), mp.IsAdded), 349 ) 350 351 for i := 0; i < len(mp.ContractList); i++ { 352 builder.WriteString("\t\t\t\t\t\t") 353 builder.WriteString(mp.ContractList[i].String()) 354 builder.Write([]byte{'\n'}) 355 } 356 357 return strings.TrimSpace(builder.String()) 358 } 359 360 // FixShortAddr is to fix the short address problem in the OKC test-net. 361 // The normal len(BlockedContract.Address) should be 20, 362 // but there are some BlockedContract.Address in OKC test-net that have a length of 4. 363 // The fix is to pad the leading bits of the short address with zeros until the length is 20. 364 func (mp *ManageContractMethodBlockedListProposal) FixShortAddr() { 365 for i := 0; i < len(mp.ContractList); i++ { 366 if len(mp.ContractList[i].Address) < 20 { 367 validAddress := make([]byte, 20-len(mp.ContractList[i].Address), 20) 368 validAddress = append(validAddress, mp.ContractList[i].Address...) 369 mp.ContractList[i].Address = validAddress 370 } 371 } 372 } 373 374 type ManageSysContractAddressProposal struct { 375 Title string `json:"title" yaml:"title"` 376 Description string `json:"description" yaml:"description"` 377 // Contract Address 378 ContractAddr sdk.AccAddress `json:"contract_address" yaml:"contract_address"` 379 IsAdded bool `json:"is_added" yaml:"is_added"` 380 } 381 382 // NewManageSysContractAddressProposal creates a new instance of NewManageSysContractAddressProposal 383 func NewManageSysContractAddressProposal(title, description string, addr sdk.AccAddress, isAdded bool, 384 ) ManageSysContractAddressProposal { 385 return ManageSysContractAddressProposal{ 386 Title: title, 387 Description: description, 388 ContractAddr: addr, 389 IsAdded: isAdded, 390 } 391 } 392 393 // GetTitle returns title of a manage system contract address proposal object 394 func (mp ManageSysContractAddressProposal) GetTitle() string { 395 return mp.Title 396 } 397 398 // GetDescription returns description of a manage system contract address proposal object 399 func (mp ManageSysContractAddressProposal) GetDescription() string { 400 return mp.Description 401 } 402 403 // ProposalRoute returns route key of a manage system contract address proposal object 404 func (mp ManageSysContractAddressProposal) ProposalRoute() string { 405 return RouterKey 406 } 407 408 // ProposalType returns type of a manage system contract address proposal object 409 func (mp ManageSysContractAddressProposal) ProposalType() string { 410 return proposalTypeManageSysContractAddress 411 } 412 413 // ValidateBasic validates a manage system contract address proposal 414 func (mp ManageSysContractAddressProposal) ValidateBasic() sdk.Error { 415 //will delete it after upgrade venus3 416 if global.GetGlobalHeight() > 0 && !types.HigherThanVenus3(global.GetGlobalHeight()) { 417 return govtypes.ErrInvalidProposalContent("not support system contract address proposal") 418 } 419 420 if len(strings.TrimSpace(mp.Title)) == 0 { 421 return govtypes.ErrInvalidProposalContent("title is required") 422 } 423 424 if len(mp.Title) > govtypes.MaxTitleLength { 425 return govtypes.ErrInvalidProposalContent("title length is longer than the maximum title length") 426 } 427 428 if len(mp.Description) == 0 { 429 return govtypes.ErrInvalidProposalContent("description is required") 430 } 431 432 if len(mp.Description) > govtypes.MaxDescriptionLength { 433 return govtypes.ErrInvalidProposalContent("description length is longer than the maximum description length") 434 } 435 436 if mp.ProposalType() != proposalTypeManageSysContractAddress { 437 return govtypes.ErrInvalidProposalType(mp.ProposalType()) 438 } 439 440 if mp.IsAdded && mp.ContractAddr.Empty() { 441 return govtypes.ErrInvalidProposalContent("is_added true, contract address required") 442 } 443 444 return nil 445 } 446 447 // String returns a human readable string representation of a ManageSysContractAddressProposal 448 func (mp ManageSysContractAddressProposal) String() string { 449 var builder strings.Builder 450 builder.WriteString( 451 fmt.Sprintf(`ManageSysContractAddressProposal: 452 Title: %s 453 Description: %s 454 Type: %s 455 ContractAddr: %s 456 IsAdded: %t 457 `, 458 mp.Title, mp.Description, mp.ProposalType(), mp.ContractAddr.String(), mp.IsAdded), 459 ) 460 return strings.TrimSpace(builder.String()) 461 } 462 463 type ManageContractByteCodeProposal struct { 464 Title string `json:"title" yaml:"title"` 465 Description string `json:"description" yaml:"description"` 466 Contract sdk.AccAddress `json:"contract" yaml:"contract"` 467 SubstituteContract sdk.AccAddress `json:"substitute_contract" yaml:"substitute_contract"` 468 } 469 470 func NewManageContractByteCodeProposal(title, description string, Contract sdk.AccAddress, SubstituteContract sdk.AccAddress) ManageContractByteCodeProposal { 471 return ManageContractByteCodeProposal{ 472 Title: title, 473 Description: description, 474 Contract: Contract, 475 SubstituteContract: SubstituteContract, 476 } 477 } 478 479 func (mp ManageContractByteCodeProposal) GetTitle() string { 480 return mp.Title 481 } 482 483 func (mp ManageContractByteCodeProposal) GetDescription() string { 484 return mp.Description 485 } 486 487 func (mp ManageContractByteCodeProposal) ProposalRoute() string { 488 return RouterKey 489 } 490 491 func (mp ManageContractByteCodeProposal) ProposalType() string { 492 return proposalTypeManageContractByteCode 493 } 494 495 func (mp ManageContractByteCodeProposal) ValidateBasic() sdk.Error { 496 497 if len(strings.TrimSpace(mp.Title)) == 0 { 498 return govtypes.ErrInvalidProposalContent("title is required") 499 } 500 if len(mp.Title) > govtypes.MaxTitleLength { 501 return govtypes.ErrInvalidProposalContent("title length is longer than the maximum title length") 502 } 503 504 if len(mp.Description) == 0 { 505 return govtypes.ErrInvalidProposalContent("description is required") 506 } 507 508 if len(mp.Description) > govtypes.MaxDescriptionLength { 509 return govtypes.ErrInvalidProposalContent("description length is longer than the maximum description length") 510 } 511 512 if mp.ProposalType() != proposalTypeManageContractByteCode { 513 return govtypes.ErrInvalidProposalType(mp.ProposalType()) 514 } 515 516 return nil 517 } 518 func (mp ManageContractByteCodeProposal) String() string { 519 var builder strings.Builder 520 builder.WriteString( 521 fmt.Sprintf(`ManageContractByteCodeProposal: 522 Title: %s 523 Description: %s 524 Type: %s 525 Contract: %s 526 SubstituteContract: %s 527 `, 528 mp.Title, mp.Description, mp.ProposalType(), mp.Contract.String(), mp.SubstituteContract.String()), 529 ) 530 return strings.TrimSpace(builder.String()) 531 }