github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evm/types/proposal_test.go (about) 1 package types 2 3 import ( 4 "math/big" 5 "strings" 6 "testing" 7 8 ethcmn "github.com/ethereum/go-ethereum/common" 9 "github.com/fibonacci-chain/fbc/libs/tendermint/types" 10 govtypes "github.com/fibonacci-chain/fbc/x/gov/types" 11 "github.com/stretchr/testify/suite" 12 ) 13 14 const ( 15 expectedTitle = "default title" 16 expectedDescription = "default description" 17 expectedManageContractDeploymentWhitelistProposalString = `ManageContractDeploymentWhitelistProposal: 18 Title: default title 19 Description: default description 20 Type: ManageContractDeploymentWhitelist 21 IsAdded: true 22 DistributorAddrs: 23 fb1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpvmzvy 24 fb1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpu60h3k` 25 expectedManageContractBlockedListProposalString = `ManageContractBlockedListProposal: 26 Title: default title 27 Description: default description 28 Type: ManageContractBlockedList 29 IsAdded: true 30 ContractAddrs: 31 fb1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpvmzvy 32 fb1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpu60h3k` 33 expectedManageContractMethodBlockedListProposalString = `ManageContractMethodBlockedListProposal: 34 Title: default title 35 Description: default description 36 Type: ManageContractMethodBlockedList 37 IsAdded: true 38 ContractList: 39 Address: fb1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpvmzvy 40 Method List: 41 Sign: 0x11111111Extra: TEST1 42 Sign: 0x22222222Extra: TEST2 43 Address: fb1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpu60h3k 44 Method List: 45 Sign: 0x33333333Extra: TEST3 46 Sign: 0x44444444Extra: TEST4` 47 ) 48 49 type ProposalTestSuite struct { 50 suite.Suite 51 strBuilder strings.Builder 52 addrs AddressList 53 blockedContractList BlockedContractList 54 } 55 56 func TestProposalTestSuite(t *testing.T) { 57 proposalTestSuite := ProposalTestSuite{ 58 addrs: AddressList{ 59 ethcmn.BytesToAddress([]byte{0x0}).Bytes(), 60 ethcmn.BytesToAddress([]byte{0x1}).Bytes(), 61 }, 62 blockedContractList: BlockedContractList{ 63 BlockedContract{ 64 Address: ethcmn.BytesToAddress([]byte{0x0}).Bytes(), 65 BlockMethods: ContractMethods{ 66 ContractMethod{Sign: "0x11111111", Extra: "TEST1"}, 67 ContractMethod{Sign: "0x22222222", Extra: "TEST2"}, 68 }, 69 }, 70 BlockedContract{ 71 Address: ethcmn.BytesToAddress([]byte{0x1}).Bytes(), 72 BlockMethods: ContractMethods{ 73 ContractMethod{Sign: "0x33333333", Extra: "TEST3"}, 74 ContractMethod{Sign: "0x44444444", Extra: "TEST4"}, 75 }, 76 }, 77 }, 78 } 79 suite.Run(t, &proposalTestSuite) 80 } 81 82 func (suite *ProposalTestSuite) TestProposal_ManageContractDeploymentWhitelistProposal() { 83 proposal := NewManageContractDeploymentWhitelistProposal( 84 expectedTitle, 85 expectedDescription, 86 suite.addrs, 87 true, 88 ) 89 90 suite.Require().Equal(expectedTitle, proposal.GetTitle()) 91 suite.Require().Equal(expectedDescription, proposal.GetDescription()) 92 suite.Require().Equal(RouterKey, proposal.ProposalRoute()) 93 suite.Require().Equal(proposalTypeManageContractDeploymentWhitelist, proposal.ProposalType()) 94 suite.Require().Equal(expectedManageContractDeploymentWhitelistProposalString, proposal.String()) 95 96 testCases := []struct { 97 msg string 98 prepare func() 99 expectedError bool 100 }{ 101 { 102 "pass", 103 func() {}, 104 false, 105 }, 106 { 107 "empty title", 108 func() { 109 proposal.Title = "" 110 }, 111 true, 112 }, 113 { 114 "overlong title", 115 func() { 116 for i := 0; i < govtypes.MaxTitleLength+1; i++ { 117 suite.strBuilder.WriteByte('a') 118 } 119 proposal.Title = suite.strBuilder.String() 120 }, 121 true, 122 }, 123 { 124 "empty description", 125 func() { 126 proposal.Description = "" 127 proposal.Title = expectedTitle 128 }, 129 true, 130 }, 131 { 132 "overlong description", 133 func() { 134 suite.strBuilder.Reset() 135 for i := 0; i < govtypes.MaxDescriptionLength+1; i++ { 136 suite.strBuilder.WriteByte('a') 137 } 138 proposal.Description = suite.strBuilder.String() 139 }, 140 true, 141 }, 142 { 143 "duplicated distributor addresses", 144 func() { 145 // add a duplicated address into DistributorAddrs 146 proposal.DistributorAddrs = append(proposal.DistributorAddrs, proposal.DistributorAddrs[0]) 147 proposal.Description = expectedDescription 148 }, 149 true, 150 }, 151 { 152 "empty distributor addresses", 153 func() { 154 proposal.DistributorAddrs = nil 155 }, 156 true, 157 }, 158 { 159 "oversize distributor addresses", 160 func() { 161 for i := int64(0); i <= maxAddressListLength; i++ { 162 testAddr := ethcmn.BigToAddress(big.NewInt(i)).Bytes() 163 proposal.DistributorAddrs = append(proposal.DistributorAddrs, testAddr) 164 } 165 }, 166 true, 167 }, 168 } 169 170 for _, tc := range testCases { 171 suite.Run(tc.msg, func() { 172 tc.prepare() 173 174 err := proposal.ValidateBasic() 175 176 if tc.expectedError { 177 suite.Require().Error(err) 178 } else { 179 suite.Require().NoError(err) 180 } 181 }) 182 } 183 } 184 185 func (suite *ProposalTestSuite) TestProposal_ManageContractBlockedListProposal() { 186 proposal := NewManageContractBlockedListProposal( 187 expectedTitle, 188 expectedDescription, 189 suite.addrs, 190 true, 191 ) 192 193 suite.Require().Equal(expectedTitle, proposal.GetTitle()) 194 suite.Require().Equal(expectedDescription, proposal.GetDescription()) 195 suite.Require().Equal(RouterKey, proposal.ProposalRoute()) 196 suite.Require().Equal(proposalTypeManageContractBlockedList, proposal.ProposalType()) 197 suite.Require().Equal(expectedManageContractBlockedListProposalString, proposal.String()) 198 199 testCases := []struct { 200 msg string 201 prepare func() 202 expectedError bool 203 }{ 204 { 205 "pass", 206 func() {}, 207 false, 208 }, 209 { 210 "empty title", 211 func() { 212 proposal.Title = "" 213 }, 214 true, 215 }, 216 { 217 "overlong title", 218 func() { 219 for i := 0; i < govtypes.MaxTitleLength+1; i++ { 220 suite.strBuilder.WriteByte('a') 221 } 222 proposal.Title = suite.strBuilder.String() 223 }, 224 true, 225 }, 226 { 227 "empty description", 228 func() { 229 proposal.Description = "" 230 proposal.Title = expectedTitle 231 }, 232 true, 233 }, 234 { 235 "overlong description", 236 func() { 237 suite.strBuilder.Reset() 238 for i := 0; i < govtypes.MaxDescriptionLength+1; i++ { 239 suite.strBuilder.WriteByte('a') 240 } 241 proposal.Description = suite.strBuilder.String() 242 }, 243 true, 244 }, 245 { 246 "duplicated contract addresses", 247 func() { 248 // add a duplicated address into ContractAddrs 249 proposal.ContractAddrs = append(proposal.ContractAddrs, proposal.ContractAddrs[0]) 250 proposal.Description = expectedDescription 251 }, 252 true, 253 }, 254 { 255 "empty contract addresses", 256 func() { 257 proposal.ContractAddrs = nil 258 }, 259 true, 260 }, 261 { 262 "oversize contract addresses", 263 func() { 264 for i := int64(0); i <= maxAddressListLength; i++ { 265 testAddr := ethcmn.BigToAddress(big.NewInt(i)).Bytes() 266 proposal.ContractAddrs = append(proposal.ContractAddrs, testAddr) 267 } 268 }, 269 true, 270 }, 271 } 272 273 for _, tc := range testCases { 274 suite.Run(tc.msg, func() { 275 tc.prepare() 276 277 err := proposal.ValidateBasic() 278 279 if tc.expectedError { 280 suite.Require().Error(err) 281 } else { 282 suite.Require().NoError(err) 283 } 284 }) 285 } 286 } 287 288 func (suite *ProposalTestSuite) TestProposal_ManageContractMethodBlockedListProposal() { 289 proposal := NewManageContractMethodBlockedListProposal( 290 expectedTitle, 291 expectedDescription, 292 suite.blockedContractList, 293 true, 294 ) 295 296 suite.Require().Equal(expectedTitle, proposal.GetTitle()) 297 suite.Require().Equal(expectedDescription, proposal.GetDescription()) 298 suite.Require().Equal(RouterKey, proposal.ProposalRoute()) 299 suite.Require().Equal(proposalTypeManageContractMethodBlockedList, proposal.ProposalType()) 300 suite.Require().Equal(expectedManageContractMethodBlockedListProposalString, proposal.String()) 301 302 testCases := []struct { 303 msg string 304 prepare func() 305 expectedError bool 306 }{ 307 { 308 "pass", 309 func() {}, 310 false, 311 }, 312 { 313 "empty title", 314 func() { 315 proposal.Title = "" 316 }, 317 true, 318 }, 319 { 320 "overlong title", 321 func() { 322 for i := 0; i < govtypes.MaxTitleLength+1; i++ { 323 suite.strBuilder.WriteByte('a') 324 } 325 proposal.Title = suite.strBuilder.String() 326 }, 327 true, 328 }, 329 { 330 "empty description", 331 func() { 332 proposal.Description = "" 333 proposal.Title = expectedTitle 334 }, 335 true, 336 }, 337 { 338 "overlong description", 339 func() { 340 suite.strBuilder.Reset() 341 for i := 0; i < govtypes.MaxDescriptionLength+1; i++ { 342 suite.strBuilder.WriteByte('a') 343 } 344 proposal.Description = suite.strBuilder.String() 345 }, 346 true, 347 }, 348 { 349 "duplicated contract addresses", 350 func() { 351 // add a duplicated address into ContractAddrs 352 proposal.ContractList = append(proposal.ContractList, proposal.ContractList[0]) 353 proposal.Description = expectedDescription 354 }, 355 true, 356 }, 357 { 358 "empty contract addresses", 359 func() { 360 proposal.ContractList = nil 361 }, 362 true, 363 }, 364 { 365 "oversize contract addresses", 366 func() { 367 for i := int64(0); i <= maxAddressListLength; i++ { 368 testAddr := ethcmn.BigToAddress(big.NewInt(i)).Bytes() 369 testbc := BlockedContract{Address: testAddr, BlockMethods: nil} 370 proposal.ContractList = append(proposal.ContractList, testbc) 371 } 372 }, 373 true, 374 }, 375 { 376 "empty contract addresses", 377 func() { 378 for i := int64(0); i <= maxAddressListLength; i++ { 379 testbc := BlockedContract{Address: nil, BlockMethods: nil} 380 proposal.ContractList = append(proposal.ContractList, testbc) 381 } 382 }, 383 true, 384 }, 385 { 386 "duplicated contract method", 387 func() { 388 proposal.ContractList[0].BlockMethods = append(proposal.ContractList[0].BlockMethods, proposal.ContractList[0].BlockMethods...) 389 }, 390 true, 391 }, 392 } 393 394 for _, tc := range testCases { 395 suite.Run(tc.msg, func() { 396 tc.prepare() 397 398 err := proposal.ValidateBasic() 399 400 if tc.expectedError { 401 suite.Require().Error(err) 402 } else { 403 suite.Require().NoError(err) 404 } 405 }) 406 } 407 } 408 409 func (suite *ProposalTestSuite) TestProposal_ManageSysContractAddressProposal() { 410 411 const expectedManageSysContractAddressProposalString = `ManageSysContractAddressProposal: 412 Title: default title 413 Description: default description 414 Type: ManageSysContractAddress 415 ContractAddr: fb1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpvmzvy 416 IsAdded: true` 417 418 proposal := NewManageSysContractAddressProposal( 419 expectedTitle, 420 expectedDescription, 421 ethcmn.BytesToAddress([]byte{0x0}).Bytes(), 422 true, 423 ) 424 types.UnittestOnlySetMilestoneVenus3Height(-1) 425 suite.Require().Equal(expectedTitle, proposal.GetTitle()) 426 suite.Require().Equal(expectedDescription, proposal.GetDescription()) 427 suite.Require().Equal(RouterKey, proposal.ProposalRoute()) 428 suite.Require().Equal(proposalTypeManageSysContractAddress, proposal.ProposalType()) 429 suite.Require().Equal(expectedManageSysContractAddressProposalString, proposal.String()) 430 431 testCases := []struct { 432 msg string 433 prepare func() 434 expectedError bool 435 }{ 436 { 437 "pass", 438 func() { 439 }, 440 false, 441 }, 442 { 443 "pass", 444 func() { 445 proposal.IsAdded = false 446 proposal.ContractAddr = nil 447 }, 448 false, 449 }, 450 { 451 "empty title", 452 func() { 453 proposal.Title = "" 454 }, 455 true, 456 }, 457 { 458 "overlong title", 459 func() { 460 for i := 0; i < govtypes.MaxTitleLength+1; i++ { 461 suite.strBuilder.WriteByte('a') 462 } 463 proposal.Title = suite.strBuilder.String() 464 }, 465 true, 466 }, 467 { 468 "empty description", 469 func() { 470 proposal.Description = "" 471 proposal.Title = expectedTitle 472 }, 473 true, 474 }, 475 { 476 "overlong description", 477 func() { 478 suite.strBuilder.Reset() 479 for i := 0; i < govtypes.MaxDescriptionLength+1; i++ { 480 suite.strBuilder.WriteByte('a') 481 } 482 proposal.Description = suite.strBuilder.String() 483 }, 484 true, 485 }, 486 { 487 "is_added true, contract address required", 488 func() { 489 proposal.IsAdded = true 490 proposal.ContractAddr = nil 491 }, 492 true, 493 }, 494 } 495 496 for _, tc := range testCases { 497 suite.Run(tc.msg, func() { 498 tc.prepare() 499 500 err := proposal.ValidateBasic() 501 502 if tc.expectedError { 503 suite.Require().Error(err) 504 } else { 505 suite.Require().NoError(err) 506 } 507 }) 508 } 509 } 510 511 func (suite *ProposalTestSuite) TestFixShortAddr() { 512 testCases := []struct { 513 msg string 514 shouldFix bool 515 contractList BlockedContractList 516 expectedFixed bool 517 }{ 518 { 519 "pass after fix", 520 true, 521 []BlockedContract{{Address: []byte{0x3}}}, 522 true, 523 }, 524 { 525 "not pass if not fix", 526 false, 527 []BlockedContract{{Address: []byte{0x3}}}, 528 false, 529 }, 530 } 531 for _, tc := range testCases { 532 suite.Run(tc.msg, func() { 533 534 proposal := NewManageContractMethodBlockedListProposal( 535 "default title", 536 "default description", 537 tc.contractList, 538 true, 539 ) 540 if tc.shouldFix { 541 proposal.FixShortAddr() 542 } 543 544 if tc.expectedFixed { 545 suite.Require().Equal(len(proposal.ContractList[0].Address), 20) 546 } else { 547 suite.Require().NotEqual(len(proposal.ContractList[0].Address), 20) 548 } 549 }) 550 } 551 }