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  }