code.vegaprotocol.io/vega@v0.79.0/commands/proposal_submission_update_asset_test.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package commands_test
    17  
    18  import (
    19  	"testing"
    20  
    21  	"code.vegaprotocol.io/vega/commands"
    22  	types "code.vegaprotocol.io/vega/protos/vega"
    23  	commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"
    24  
    25  	"github.com/stretchr/testify/assert"
    26  )
    27  
    28  func TestCheckProposalSubmissionForUpdateAsset(t *testing.T) {
    29  	t.Run("Submitting an asset update without new asset fails", TestUpdateAssetSubmissionWithoutUpdateAssetFails)
    30  	t.Run("Submitting an asset update without asset ID fails", TestUpdateAssetSubmissionWithoutAssetIDFails)
    31  	t.Run("Submitting an asset update with asset ID succeeds", TestUpdateAssetSubmissionWithAssetIDSucceeds)
    32  	t.Run("Submitting an asset update without changes fails", TestUpdateAssetSubmissionWithoutChangesFails)
    33  	t.Run("Submitting an asset update without source fails", TestUpdateAssetSubmissionWithoutSourceFails)
    34  	t.Run("Submitting an ERC20 asset update without ERC20 asset fails", testUpdateERC20AssetChangeSubmissionWithoutErc20AssetFails)
    35  	t.Run("Submitting an ERC20 asset update with invalid lifetime limit fails", testUpdateERC20AssetChangeSubmissionWithInvalidLifetimeLimitFails)
    36  	t.Run("Submitting an ERC20 asset update with valid lifetime limit succeeds", testUpdateERC20AssetChangeSubmissionWithValidLifetimeLimitSucceeds)
    37  	t.Run("Submitting an ERC20 asset update with invalid withdrawal threshold fails", testUpdateERC20AssetChangeSubmissionWithInvalidWithdrawalThresholdFails)
    38  	t.Run("Submitting an ERC20 asset update with valid withdrawal threshold succeeds", testUpdateERC20AssetChangeSubmissionWithValidWithdrawalThresholdSucceeds)
    39  	t.Run("Submitting an ERC20 asset change with invalid quantum fails", testUpdateERC20AssetChangeSubmissionWithInvalidQuantumFails)
    40  	t.Run("Submitting an ERC20 asset change with valid quantum succeeds", testUpdateERC20AssetChangeSubmissionWithValidQuantumSucceeds)
    41  }
    42  
    43  func TestUpdateAssetSubmissionWithoutUpdateAssetFails(t *testing.T) {
    44  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
    45  		Terms: &types.ProposalTerms{
    46  			Change: &types.ProposalTerms_UpdateAsset{},
    47  		},
    48  	})
    49  
    50  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_asset"), commands.ErrIsRequired)
    51  }
    52  
    53  func TestUpdateAssetSubmissionWithAssetIDSucceeds(t *testing.T) {
    54  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
    55  		Terms: &types.ProposalTerms{
    56  			Change: &types.ProposalTerms_UpdateAsset{
    57  				UpdateAsset: &types.UpdateAsset{
    58  					AssetId: "",
    59  				},
    60  			},
    61  		},
    62  	})
    63  
    64  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_asset.asset_id"), commands.ErrIsRequired)
    65  }
    66  
    67  func TestUpdateAssetSubmissionWithoutAssetIDFails(t *testing.T) {
    68  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
    69  		Terms: &types.ProposalTerms{
    70  			Change: &types.ProposalTerms_UpdateAsset{
    71  				UpdateAsset: &types.UpdateAsset{
    72  					AssetId: "invalid",
    73  				},
    74  			},
    75  		},
    76  	})
    77  
    78  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_asset.asset_id"), commands.ErrShouldBeAValidVegaID)
    79  }
    80  
    81  func TestUpdateAssetSubmissionWithoutChangesFails(t *testing.T) {
    82  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
    83  		Terms: &types.ProposalTerms{
    84  			Change: &types.ProposalTerms_UpdateAsset{
    85  				UpdateAsset: &types.UpdateAsset{},
    86  			},
    87  		},
    88  	})
    89  
    90  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_asset.changes"), commands.ErrIsRequired)
    91  }
    92  
    93  func TestUpdateAssetSubmissionWithoutSourceFails(t *testing.T) {
    94  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
    95  		Terms: &types.ProposalTerms{
    96  			Change: &types.ProposalTerms_UpdateAsset{
    97  				UpdateAsset: &types.UpdateAsset{
    98  					Changes: &types.AssetDetailsUpdate{},
    99  				},
   100  			},
   101  		},
   102  	})
   103  
   104  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_asset.changes.source"), commands.ErrIsRequired)
   105  }
   106  
   107  func testUpdateERC20AssetChangeSubmissionWithoutErc20AssetFails(t *testing.T) {
   108  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   109  		Terms: &types.ProposalTerms{
   110  			Change: &types.ProposalTerms_UpdateAsset{
   111  				UpdateAsset: &types.UpdateAsset{
   112  					Changes: &types.AssetDetailsUpdate{
   113  						Source: &types.AssetDetailsUpdate_Erc20{},
   114  					},
   115  				},
   116  			},
   117  		},
   118  	})
   119  
   120  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_asset.changes.source.erc20"), commands.ErrIsRequired)
   121  }
   122  
   123  func testUpdateERC20AssetChangeSubmissionWithInvalidLifetimeLimitFails(t *testing.T) {
   124  	tcs := []struct {
   125  		name  string
   126  		err   error
   127  		value string
   128  	}{
   129  		{
   130  			name:  "Without lifetime limit",
   131  			value: "",
   132  			err:   commands.ErrIsRequired,
   133  		}, {
   134  			name:  "With not-a-number lifetime limit",
   135  			value: "forty-two",
   136  			err:   commands.ErrIsNotValidNumber,
   137  		}, {
   138  			name:  "With zero lifetime limit",
   139  			value: "0",
   140  			err:   commands.ErrMustBePositive,
   141  		}, {
   142  			name:  "With negative lifetime limit",
   143  			value: "-10",
   144  			err:   commands.ErrMustBePositive,
   145  		},
   146  	}
   147  
   148  	for _, tc := range tcs {
   149  		t.Run(tc.name, func(tt *testing.T) {
   150  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
   151  				Terms: &types.ProposalTerms{
   152  					Change: &types.ProposalTerms_UpdateAsset{
   153  						UpdateAsset: &types.UpdateAsset{
   154  							Changes: &types.AssetDetailsUpdate{
   155  								Source: &types.AssetDetailsUpdate_Erc20{
   156  									Erc20: &types.ERC20Update{
   157  										LifetimeLimit: tc.value,
   158  									},
   159  								},
   160  							},
   161  						},
   162  					},
   163  				},
   164  			})
   165  
   166  			assert.Contains(tt, err.Get("proposal_submission.terms.change.update_asset.changes.source.erc20.lifetime_limit"), tc.err)
   167  		})
   168  	}
   169  }
   170  
   171  func testUpdateERC20AssetChangeSubmissionWithValidLifetimeLimitSucceeds(t *testing.T) {
   172  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   173  		Terms: &types.ProposalTerms{
   174  			Change: &types.ProposalTerms_UpdateAsset{
   175  				UpdateAsset: &types.UpdateAsset{
   176  					Changes: &types.AssetDetailsUpdate{
   177  						Source: &types.AssetDetailsUpdate_Erc20{
   178  							Erc20: &types.ERC20Update{
   179  								LifetimeLimit: "100",
   180  							},
   181  						},
   182  					},
   183  				},
   184  			},
   185  		},
   186  	})
   187  
   188  	assert.Empty(t, err.Get("proposal_submission.terms.change.update_asset.changes.source.erc20.lifetime_limit"))
   189  }
   190  
   191  func testUpdateERC20AssetChangeSubmissionWithInvalidWithdrawalThresholdFails(t *testing.T) {
   192  	tcs := []struct {
   193  		name  string
   194  		err   error
   195  		value string
   196  	}{
   197  		{
   198  			name:  "Without withdraw threshold",
   199  			value: "",
   200  			err:   commands.ErrIsRequired,
   201  		}, {
   202  			name:  "With not-a-number withdraw threshold",
   203  			value: "forty-two",
   204  			err:   commands.ErrIsNotValidNumber,
   205  		}, {
   206  			name:  "With zero withdraw threshold",
   207  			value: "0",
   208  			err:   commands.ErrMustBePositive,
   209  		}, {
   210  			name:  "With negative withdraw threshold",
   211  			value: "-10",
   212  			err:   commands.ErrMustBePositive,
   213  		},
   214  	}
   215  
   216  	for _, tc := range tcs {
   217  		t.Run(tc.name, func(tt *testing.T) {
   218  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
   219  				Terms: &types.ProposalTerms{
   220  					Change: &types.ProposalTerms_UpdateAsset{
   221  						UpdateAsset: &types.UpdateAsset{
   222  							Changes: &types.AssetDetailsUpdate{
   223  								Source: &types.AssetDetailsUpdate_Erc20{
   224  									Erc20: &types.ERC20Update{
   225  										WithdrawThreshold: tc.value,
   226  									},
   227  								},
   228  							},
   229  						},
   230  					},
   231  				},
   232  			})
   233  
   234  			assert.Contains(tt, err.Get("proposal_submission.terms.change.update_asset.changes.source.erc20.withdraw_threshold"), tc.err)
   235  		})
   236  	}
   237  }
   238  
   239  func testUpdateERC20AssetChangeSubmissionWithValidWithdrawalThresholdSucceeds(t *testing.T) {
   240  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   241  		Terms: &types.ProposalTerms{
   242  			Change: &types.ProposalTerms_UpdateAsset{
   243  				UpdateAsset: &types.UpdateAsset{
   244  					Changes: &types.AssetDetailsUpdate{
   245  						Source: &types.AssetDetailsUpdate_Erc20{
   246  							Erc20: &types.ERC20Update{
   247  								WithdrawThreshold: "100",
   248  							},
   249  						},
   250  					},
   251  				},
   252  			},
   253  		},
   254  	})
   255  
   256  	assert.Empty(t, err.Get("proposal_submission.terms.change.update_asset.changes.source.erc20.withdraw_threshold"))
   257  }
   258  
   259  func testUpdateERC20AssetChangeSubmissionWithInvalidQuantumFails(t *testing.T) {
   260  	tcs := []struct {
   261  		name  string
   262  		err   error
   263  		value string
   264  	}{
   265  		{
   266  			name:  "Without withdraw quantum",
   267  			value: "",
   268  			err:   commands.ErrIsRequired,
   269  		}, {
   270  			name:  "With not-a-number quantum",
   271  			value: "forty-two",
   272  			err:   commands.ErrIsNotValidNumber,
   273  		}, {
   274  			name:  "With zero withdraw quantum",
   275  			value: "0",
   276  			err:   commands.ErrMustBePositive,
   277  		}, {
   278  			name:  "With negative withdraw quantum",
   279  			value: "-10",
   280  			err:   commands.ErrMustBePositive,
   281  		},
   282  	}
   283  
   284  	for _, tc := range tcs {
   285  		t.Run(tc.name, func(tt *testing.T) {
   286  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
   287  				Terms: &types.ProposalTerms{
   288  					Change: &types.ProposalTerms_UpdateAsset{
   289  						UpdateAsset: &types.UpdateAsset{
   290  							Changes: &types.AssetDetailsUpdate{
   291  								Quantum: tc.value,
   292  								Source: &types.AssetDetailsUpdate_Erc20{
   293  									Erc20: &types.ERC20Update{},
   294  								},
   295  							},
   296  						},
   297  					},
   298  				},
   299  			})
   300  
   301  			assert.Contains(tt, err.Get("proposal_submission.terms.change.update_asset.changes.quantum"), tc.err)
   302  		})
   303  	}
   304  }
   305  
   306  func testUpdateERC20AssetChangeSubmissionWithValidQuantumSucceeds(t *testing.T) {
   307  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   308  		Terms: &types.ProposalTerms{
   309  			Change: &types.ProposalTerms_UpdateAsset{
   310  				UpdateAsset: &types.UpdateAsset{
   311  					Changes: &types.AssetDetailsUpdate{
   312  						Quantum: "0.1",
   313  						Source: &types.AssetDetailsUpdate_Erc20{
   314  							Erc20: &types.ERC20Update{},
   315  						},
   316  					},
   317  				},
   318  			},
   319  		},
   320  	})
   321  
   322  	assert.Empty(t, err.Get("proposal_submission.terms.change.update_asset.changes.quantum"))
   323  }