github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/wasm/types/tx_test.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "fmt" 6 "strings" 7 "testing" 8 9 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 ) 13 14 const firstCodeID = 1 15 16 func TestStoreCodeValidation(t *testing.T) { 17 bad, err := sdk.AccAddressFromHex("012345") 18 require.NoError(t, err) 19 badAddress := bad.String() 20 // proper address size 21 goodAddress := sdk.AccAddress(make([]byte, ContractAddrLen)).String() 22 sdk.GetConfig().SetAddressVerifier(VerifyAddressLen()) 23 cases := map[string]struct { 24 msg MsgStoreCode 25 valid bool 26 }{ 27 "empty": { 28 msg: MsgStoreCode{}, 29 valid: false, 30 }, 31 "correct minimal": { 32 msg: MsgStoreCode{ 33 Sender: goodAddress, 34 WASMByteCode: []byte("foo"), 35 }, 36 valid: true, 37 }, 38 "missing code": { 39 msg: MsgStoreCode{ 40 Sender: goodAddress, 41 }, 42 valid: false, 43 }, 44 "bad sender minimal": { 45 msg: MsgStoreCode{ 46 Sender: badAddress, 47 WASMByteCode: []byte("foo"), 48 }, 49 valid: false, 50 }, 51 "correct maximal": { 52 msg: MsgStoreCode{ 53 Sender: goodAddress, 54 WASMByteCode: []byte("foo"), 55 }, 56 valid: true, 57 }, 58 "invalid InstantiatePermission": { 59 msg: MsgStoreCode{ 60 Sender: goodAddress, 61 WASMByteCode: []byte("foo"), 62 InstantiatePermission: &AccessConfig{Permission: AccessTypeOnlyAddress, Address: badAddress}, 63 }, 64 valid: false, 65 }, 66 } 67 68 for name, tc := range cases { 69 t.Run(name, func(t *testing.T) { 70 err := tc.msg.ValidateBasic() 71 if tc.valid { 72 assert.NoError(t, err) 73 } else { 74 assert.Error(t, err) 75 } 76 }) 77 } 78 } 79 80 func TestInstantiateContractValidation(t *testing.T) { 81 bad, err := sdk.AccAddressFromHex("012345") 82 require.NoError(t, err) 83 badAddress := bad.String() 84 // proper address size 85 goodAddress := sdk.AccAddress(make([]byte, 20)).String() 86 87 cases := map[string]struct { 88 msg MsgInstantiateContract 89 valid bool 90 }{ 91 "empty": { 92 msg: MsgInstantiateContract{}, 93 valid: false, 94 }, 95 "correct minimal": { 96 msg: MsgInstantiateContract{ 97 Sender: goodAddress, 98 CodeID: firstCodeID, 99 Label: "foo", 100 Msg: []byte("{}"), 101 }, 102 valid: true, 103 }, 104 "missing code": { 105 msg: MsgInstantiateContract{ 106 Sender: goodAddress, 107 Label: "foo", 108 Msg: []byte("{}"), 109 }, 110 valid: false, 111 }, 112 "missing label": { 113 msg: MsgInstantiateContract{ 114 Sender: goodAddress, 115 Msg: []byte("{}"), 116 }, 117 valid: false, 118 }, 119 "label too long": { 120 msg: MsgInstantiateContract{ 121 Sender: goodAddress, 122 Label: strings.Repeat("food", 33), 123 }, 124 valid: false, 125 }, 126 "bad sender minimal": { 127 msg: MsgInstantiateContract{ 128 Sender: badAddress, 129 CodeID: firstCodeID, 130 Label: "foo", 131 Msg: []byte("{}"), 132 }, 133 valid: false, 134 }, 135 "correct maximal": { 136 msg: MsgInstantiateContract{ 137 Sender: goodAddress, 138 CodeID: firstCodeID, 139 Label: "foo", 140 Msg: []byte(`{"some": "data"}`), 141 Funds: sdk.CoinAdapters{{Denom: "foobar", Amount: sdk.NewInt(200)}}, 142 }, 143 valid: true, 144 }, 145 "negative funds": { 146 msg: MsgInstantiateContract{ 147 Sender: goodAddress, 148 CodeID: firstCodeID, 149 Label: "foo", 150 Msg: []byte(`{"some": "data"}`), 151 // we cannot use sdk.NewCoin() constructors as they panic on creating invalid data (before we can test) 152 Funds: sdk.CoinAdapters{{Denom: "foobar", Amount: sdk.NewInt(-200)}}, 153 }, 154 valid: false, 155 }, 156 "non json init msg": { 157 msg: MsgInstantiateContract{ 158 Sender: goodAddress, 159 CodeID: firstCodeID, 160 Label: "foo", 161 Msg: []byte("invalid-json"), 162 }, 163 valid: false, 164 }, 165 "empty init msg": { 166 msg: MsgInstantiateContract{ 167 Sender: goodAddress, 168 CodeID: firstCodeID, 169 Label: "foo", 170 }, 171 valid: false, 172 }, 173 } 174 175 for name, tc := range cases { 176 t.Run(name, func(t *testing.T) { 177 err := tc.msg.ValidateBasic() 178 if tc.valid { 179 assert.NoError(t, err) 180 } else { 181 assert.Error(t, err) 182 } 183 }) 184 } 185 } 186 187 func TestExecuteContractValidation(t *testing.T) { 188 bad, err := sdk.AccAddressFromHex("012345") 189 require.NoError(t, err) 190 badAddress := bad.String() 191 // proper address size 192 goodAddress := sdk.AccAddress(make([]byte, 20)).String() 193 fmt.Println(badAddress, goodAddress) 194 195 cases := map[string]struct { 196 msg MsgExecuteContract 197 valid bool 198 }{ 199 "empty": { 200 msg: MsgExecuteContract{}, 201 valid: false, 202 }, 203 "correct minimal": { 204 msg: MsgExecuteContract{ 205 Sender: goodAddress, 206 Contract: goodAddress, 207 Msg: []byte("{}"), 208 }, 209 valid: true, 210 }, 211 "correct all": { 212 msg: MsgExecuteContract{ 213 Sender: goodAddress, 214 Contract: goodAddress, 215 Msg: []byte(`{"some": "data"}`), 216 Funds: sdk.CoinAdapters{{Denom: "foobar", Amount: sdk.NewInt(200)}}, 217 }, 218 valid: true, 219 }, 220 "bad sender": { 221 msg: MsgExecuteContract{ 222 Sender: badAddress, 223 Contract: goodAddress, 224 Msg: []byte(`{"some": "data"}`), 225 }, 226 valid: false, 227 }, 228 "empty sender": { 229 msg: MsgExecuteContract{ 230 Contract: goodAddress, 231 Msg: []byte(`{"some": "data"}`), 232 }, 233 valid: false, 234 }, 235 "bad contract": { 236 msg: MsgExecuteContract{ 237 Sender: goodAddress, 238 Contract: badAddress, 239 Msg: []byte(`{"some": "data"}`), 240 }, 241 valid: false, 242 }, 243 "empty contract": { 244 msg: MsgExecuteContract{ 245 Sender: goodAddress, 246 Msg: []byte(`{"some": "data"}`), 247 }, 248 valid: false, 249 }, 250 "negative funds": { 251 msg: MsgExecuteContract{ 252 Sender: goodAddress, 253 Contract: goodAddress, 254 Msg: []byte(`{"some": "data"}`), 255 Funds: sdk.CoinAdapters{{Denom: "foobar", Amount: sdk.NewInt(-1)}}, 256 }, 257 valid: false, 258 }, 259 "duplicate funds": { 260 msg: MsgExecuteContract{ 261 Sender: goodAddress, 262 Contract: goodAddress, 263 Msg: []byte(`{"some": "data"}`), 264 Funds: sdk.CoinAdapters{{Denom: "foobar", Amount: sdk.NewInt(1)}, {Denom: "foobar", Amount: sdk.NewInt(1)}}, 265 }, 266 valid: false, 267 }, 268 "non json msg": { 269 msg: MsgExecuteContract{ 270 Sender: goodAddress, 271 Contract: goodAddress, 272 Msg: []byte("invalid-json"), 273 }, 274 valid: false, 275 }, 276 "empty msg": { 277 msg: MsgExecuteContract{ 278 Sender: goodAddress, 279 Contract: goodAddress, 280 }, 281 valid: false, 282 }, 283 } 284 285 for name, tc := range cases { 286 t.Run(name, func(t *testing.T) { 287 err := tc.msg.ValidateBasic() 288 if tc.valid { 289 assert.NoError(t, err) 290 } else { 291 assert.Error(t, err) 292 } 293 }) 294 } 295 } 296 297 func TestMsgUpdateAdministrator(t *testing.T) { 298 bad, err := sdk.AccAddressFromHex("012345") 299 require.NoError(t, err) 300 badAddress := bad.String() 301 // proper address size 302 goodAddress := sdk.AccAddress(make([]byte, 20)).String() 303 otherGoodAddress := sdk.AccAddress(bytes.Repeat([]byte{0x1}, 20)).String() 304 anotherGoodAddress := sdk.AccAddress(bytes.Repeat([]byte{0x2}, 20)).String() 305 306 specs := map[string]struct { 307 src MsgUpdateAdmin 308 expErr bool 309 }{ 310 "all good": { 311 src: MsgUpdateAdmin{ 312 Sender: goodAddress, 313 NewAdmin: otherGoodAddress, 314 Contract: anotherGoodAddress, 315 }, 316 }, 317 "new admin required": { 318 src: MsgUpdateAdmin{ 319 Sender: goodAddress, 320 Contract: anotherGoodAddress, 321 }, 322 expErr: true, 323 }, 324 "bad sender": { 325 src: MsgUpdateAdmin{ 326 Sender: badAddress, 327 NewAdmin: otherGoodAddress, 328 Contract: anotherGoodAddress, 329 }, 330 expErr: true, 331 }, 332 "bad new admin": { 333 src: MsgUpdateAdmin{ 334 Sender: goodAddress, 335 NewAdmin: badAddress, 336 Contract: anotherGoodAddress, 337 }, 338 expErr: true, 339 }, 340 "bad contract addr": { 341 src: MsgUpdateAdmin{ 342 Sender: goodAddress, 343 NewAdmin: otherGoodAddress, 344 Contract: badAddress, 345 }, 346 expErr: true, 347 }, 348 "new admin same as old admin": { 349 src: MsgUpdateAdmin{ 350 Sender: goodAddress, 351 NewAdmin: goodAddress, 352 Contract: anotherGoodAddress, 353 }, 354 expErr: true, 355 }, 356 } 357 for msg, spec := range specs { 358 t.Run(msg, func(t *testing.T) { 359 err := spec.src.ValidateBasic() 360 if spec.expErr { 361 require.Error(t, err) 362 return 363 } 364 require.NoError(t, err) 365 }) 366 } 367 } 368 369 func TestMsgClearAdministrator(t *testing.T) { 370 bad, err := sdk.AccAddressFromHex("012345") 371 require.NoError(t, err) 372 badAddress := bad.String() 373 // proper address size 374 goodAddress := sdk.AccAddress(make([]byte, 20)).String() 375 anotherGoodAddress := sdk.AccAddress(bytes.Repeat([]byte{0x2}, 20)).String() 376 377 specs := map[string]struct { 378 src MsgClearAdmin 379 expErr bool 380 }{ 381 "all good": { 382 src: MsgClearAdmin{ 383 Sender: goodAddress, 384 Contract: anotherGoodAddress, 385 }, 386 }, 387 "bad sender": { 388 src: MsgClearAdmin{ 389 Sender: badAddress, 390 Contract: anotherGoodAddress, 391 }, 392 expErr: true, 393 }, 394 "bad contract addr": { 395 src: MsgClearAdmin{ 396 Sender: goodAddress, 397 Contract: badAddress, 398 }, 399 expErr: true, 400 }, 401 "contract missing": { 402 src: MsgClearAdmin{ 403 Sender: goodAddress, 404 }, 405 expErr: true, 406 }, 407 } 408 for msg, spec := range specs { 409 t.Run(msg, func(t *testing.T) { 410 err := spec.src.ValidateBasic() 411 if spec.expErr { 412 require.Error(t, err) 413 return 414 } 415 require.NoError(t, err) 416 }) 417 } 418 } 419 420 func TestMsgMigrateContract(t *testing.T) { 421 bad, err := sdk.AccAddressFromHex("012345") 422 require.NoError(t, err) 423 badAddress := bad.String() 424 // proper address size 425 goodAddress := sdk.AccAddress(make([]byte, 20)).String() 426 anotherGoodAddress := sdk.AccAddress(bytes.Repeat([]byte{0x2}, 20)).String() 427 428 specs := map[string]struct { 429 src MsgMigrateContract 430 expErr bool 431 }{ 432 "all good": { 433 src: MsgMigrateContract{ 434 Sender: goodAddress, 435 Contract: anotherGoodAddress, 436 CodeID: firstCodeID, 437 Msg: []byte("{}"), 438 }, 439 }, 440 "bad sender": { 441 src: MsgMigrateContract{ 442 Sender: badAddress, 443 Contract: anotherGoodAddress, 444 CodeID: firstCodeID, 445 }, 446 expErr: true, 447 }, 448 "empty sender": { 449 src: MsgMigrateContract{ 450 Contract: anotherGoodAddress, 451 CodeID: firstCodeID, 452 }, 453 expErr: true, 454 }, 455 "empty code": { 456 src: MsgMigrateContract{ 457 Sender: goodAddress, 458 Contract: anotherGoodAddress, 459 }, 460 expErr: true, 461 }, 462 "bad contract addr": { 463 src: MsgMigrateContract{ 464 Sender: goodAddress, 465 Contract: badAddress, 466 CodeID: firstCodeID, 467 }, 468 expErr: true, 469 }, 470 "empty contract addr": { 471 src: MsgMigrateContract{ 472 Sender: goodAddress, 473 CodeID: firstCodeID, 474 }, 475 expErr: true, 476 }, 477 "non json migrateMsg": { 478 src: MsgMigrateContract{ 479 Sender: goodAddress, 480 Contract: anotherGoodAddress, 481 CodeID: firstCodeID, 482 Msg: []byte("invalid json"), 483 }, 484 expErr: true, 485 }, 486 "empty migrateMsg": { 487 src: MsgMigrateContract{ 488 Sender: goodAddress, 489 Contract: anotherGoodAddress, 490 CodeID: firstCodeID, 491 }, 492 expErr: true, 493 }, 494 } 495 for msg, spec := range specs { 496 t.Run(msg, func(t *testing.T) { 497 err := spec.src.ValidateBasic() 498 if spec.expErr { 499 require.Error(t, err) 500 return 501 } 502 require.NoError(t, err) 503 }) 504 } 505 } 506 507 type LegacyMsg interface { 508 sdk.Msg 509 510 // Get the canonical byte representation of the Msg. 511 GetSignBytes() []byte 512 513 // Return the message type. 514 // Must be alphanumeric or empty. 515 Route() string 516 517 // Returns a human-readable string for the message, intended for utilization 518 // within tags 519 Type() string 520 } 521 522 func TestMsgJsonSignBytes(t *testing.T) { 523 const myInnerMsg = `{"foo":"bar"}` 524 specs := map[string]struct { 525 src LegacyMsg 526 exp string 527 }{ 528 "MsgInstantiateContract": { 529 src: &MsgInstantiateContract{Msg: RawContractMessage(myInnerMsg)}, 530 exp: ` 531 { 532 "type":"wasm/MsgInstantiateContract", 533 "value": {"msg": {"foo":"bar"}, "funds":[]} 534 }`, 535 }, 536 "MsgExecuteContract": { 537 src: &MsgExecuteContract{Msg: RawContractMessage(myInnerMsg)}, 538 exp: ` 539 { 540 "type":"wasm/MsgExecuteContract", 541 "value": {"msg": {"foo":"bar"}, "funds":[]} 542 }`, 543 }, 544 "MsgMigrateContract": { 545 src: &MsgMigrateContract{Msg: RawContractMessage(myInnerMsg)}, 546 exp: ` 547 { 548 "type":"wasm/MsgMigrateContract", 549 "value": {"msg": {"foo":"bar"}} 550 }`, 551 }, 552 } 553 for name, spec := range specs { 554 t.Run(name, func(t *testing.T) { 555 bz := spec.src.GetSignBytes() 556 assert.JSONEq(t, spec.exp, string(bz), "raw: %s", string(bz)) 557 }) 558 } 559 }