code.vegaprotocol.io/vega@v0.79.0/core/banking/transfer_common_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 banking_test
    17  
    18  import (
    19  	"context"
    20  	"errors"
    21  	"testing"
    22  
    23  	"code.vegaprotocol.io/vega/core/assets"
    24  	"code.vegaprotocol.io/vega/core/types"
    25  	"code.vegaprotocol.io/vega/libs/num"
    26  
    27  	"github.com/golang/mock/gomock"
    28  	"github.com/stretchr/testify/require"
    29  )
    30  
    31  func TestCheckTransfer(t *testing.T) {
    32  	e := getTestEngine(t)
    33  
    34  	transfer := &types.TransferBase{
    35  		From:            "03ae90688632c649c4beab6040ff5bd04dbde8efbf737d8673bbda792a110301",
    36  		FromAccountType: types.AccountTypeGeneral,
    37  		To:              "2e05fd230f3c9f4eaf0bdc5bfb7ca0c9d00278afc44637aab60da76653d7ccf0",
    38  		ToAccountType:   types.AccountTypeGeneral,
    39  		Asset:           "eth",
    40  		Amount:          num.NewUint(10),
    41  		Reference:       "someref",
    42  	}
    43  
    44  	e.OnMinTransferQuantumMultiple(context.Background(), num.DecimalFromFloat(1))
    45  
    46  	e.col.EXPECT().GetPartyGeneralAccount(gomock.Any(), gomock.Any()).Return(&types.Account{Balance: num.NewUint(200)}, nil).AnyTimes()
    47  
    48  	// asset exists
    49  	e.assets.EXPECT().Get(gomock.Any()).Times(2).Return(assets.NewAsset(&mockAsset{name: assetNameETH, quantum: num.DecimalFromFloat(100)}), nil)
    50  	require.EqualError(t,
    51  		e.CheckTransfer(transfer),
    52  		"could not transfer funds, less than minimal amount requested to transfer",
    53  	)
    54  
    55  	// decrease quantum multiple
    56  	e.OnMinTransferQuantumMultiple(context.Background(), num.DecimalFromFloat(0.01))
    57  	require.NoError(t, e.CheckTransfer(transfer))
    58  
    59  	// invalid asset
    60  	e.assets.EXPECT().Get(gomock.Any()).Times(1).Return(nil, errors.New("asset does not exist"))
    61  	require.EqualError(t,
    62  		e.CheckTransfer(transfer),
    63  		"could not transfer funds, asset does not exist",
    64  	)
    65  
    66  	// invalid amount
    67  	e.assets.EXPECT().Get(gomock.Any()).Times(1).Return(assets.NewAsset(&mockAsset{name: assetNameETH, quantum: num.DecimalFromFloat(100)}), nil)
    68  	transfer.Amount = num.UintZero()
    69  	require.EqualError(t,
    70  		e.CheckTransfer(transfer),
    71  		"could not transfer funds, cannot transfer zero funds",
    72  	)
    73  
    74  	e.OnTransferFeeFactorUpdate(context.Background(), num.DecimalFromFloat(0.01))
    75  	e.assets.EXPECT().Get(gomock.Any()).Times(2).Return(assets.NewAsset(&mockAsset{name: assetNameETH, quantum: num.DecimalFromFloat(100)}), nil)
    76  	// sufficient balance to cover fees
    77  	transfer.Amount = num.NewUint(100)
    78  	require.NoError(t, e.CheckTransfer(transfer))
    79  
    80  	// insufficient balance to cover fees
    81  	transfer.Amount = num.NewUint(200)
    82  	require.EqualError(t, e.CheckTransfer(transfer), "could not transfer funds, not enough funds to transfer")
    83  }
    84  
    85  func TestCheckTransferWithVestedAccount(t *testing.T) {
    86  	e := getTestEngine(t)
    87  
    88  	transfer := &types.TransferBase{
    89  		From:            "03ae90688632c649c4beab6040ff5bd04dbde8efbf737d8673bbda792a110301",
    90  		FromAccountType: types.AccountTypeVestedRewards,
    91  		To:              "03ae90688632c649c4beab6040ff5bd04dbde8efbf737d8673bbda792a110301",
    92  		ToAccountType:   types.AccountTypeGeneral,
    93  		Asset:           "eth",
    94  		Amount:          num.NewUint(10),
    95  		Reference:       "someref",
    96  	}
    97  
    98  	e.OnMinTransferQuantumMultiple(context.Background(), num.DecimalFromFloat(1))
    99  
   100  	// balance is under the min amount
   101  	e.col.EXPECT().GetPartyVestedRewardAccount(gomock.Any(), gomock.Any()).Return(&types.Account{Balance: num.NewUint(90)}, nil).Times(1)
   102  
   103  	// asset exists
   104  	e.assets.EXPECT().Get(gomock.Any()).Times(1).Return(assets.NewAsset(&mockAsset{name: assetNameETH, quantum: num.DecimalFromFloat(100)}), nil)
   105  	// try to transfer a small balance, but not the whole balance
   106  	require.EqualError(t,
   107  		e.CheckTransfer(transfer),
   108  		"transfer from vested account under minimal transfer amount must be the full balance",
   109  	)
   110  
   111  	// now we try to transfre the full amount
   112  	e.col.EXPECT().GetPartyVestedRewardAccount(gomock.Any(), gomock.Any()).Return(&types.Account{Balance: num.NewUint(90)}, nil).Times(2)
   113  	transfer.Amount = num.NewUint(90)
   114  	e.assets.EXPECT().Get(gomock.Any()).Times(1).Return(assets.NewAsset(&mockAsset{name: assetNameETH, quantum: num.DecimalFromFloat(100)}), nil)
   115  	require.NoError(t,
   116  		e.CheckTransfer(transfer),
   117  	)
   118  
   119  	// now we try again, with a balance above the min amount, but not the whole balance
   120  
   121  	e.col.EXPECT().GetPartyVestedRewardAccount(gomock.Any(), gomock.Any()).Return(&types.Account{Balance: num.NewUint(300)}, nil).Times(1)
   122  	e.assets.EXPECT().Get(gomock.Any()).Times(1).Return(assets.NewAsset(&mockAsset{name: assetNameETH, quantum: num.DecimalFromFloat(100)}), nil)
   123  
   124  	transfer.Amount = num.NewUint(110)
   125  	// try to transfer a small balance, but not the whole balance
   126  	require.NoError(t,
   127  		e.CheckTransfer(transfer),
   128  	)
   129  }
   130  
   131  func TestCheckTransferWithVestedAccountFromSubAccount(t *testing.T) {
   132  	e := getTestEngine(t)
   133  
   134  	derivedKey := "c84fbf3442a2a9f9ca87c9cefe686aed241ff49981dd8ce819dd532cd42a8427"
   135  	asset := "eth"
   136  
   137  	transfer := &types.TransferBase{
   138  		From:            "03ae90688632c649c4beab6040ff5bd04dbde8efbf737d8673bbda792a110301",
   139  		FromDerivedKey:  &derivedKey,
   140  		FromAccountType: types.AccountTypeVestedRewards,
   141  		To:              "03ae90688632c649c4beab6040ff5bd04dbde8efbf737d8673bbda792a110301",
   142  		ToAccountType:   types.AccountTypeGeneral,
   143  		Asset:           asset,
   144  		Amount:          num.NewUint(10),
   145  		Reference:       "someref",
   146  	}
   147  
   148  	e.OnMinTransferQuantumMultiple(context.Background(), num.DecimalFromFloat(1))
   149  
   150  	// balance is under the min amount
   151  	e.col.EXPECT().GetPartyVestedRewardAccount(derivedKey, gomock.Any()).Return(&types.Account{Balance: num.NewUint(90)}, nil).Times(1)
   152  
   153  	// asset exists
   154  	e.assets.EXPECT().Get(gomock.Any()).Times(1).Return(assets.NewAsset(&mockAsset{name: assetNameETH, quantum: num.DecimalFromFloat(100)}), nil)
   155  	// try to transfer a small balance, but not the whole balance
   156  	require.EqualError(t,
   157  		e.CheckTransfer(transfer),
   158  		"transfer from vested account under minimal transfer amount must be the full balance",
   159  	)
   160  
   161  	// now we try to transfer the full amount
   162  	e.col.EXPECT().GetPartyVestedRewardAccount(derivedKey, gomock.Any()).Return(&types.Account{Balance: num.NewUint(90)}, nil).Times(2)
   163  	transfer.Amount = num.NewUint(90)
   164  	e.assets.EXPECT().Get(gomock.Any()).Times(1).Return(assets.NewAsset(&mockAsset{name: assetNameETH, quantum: num.DecimalFromFloat(100)}), nil)
   165  	require.NoError(t,
   166  		e.CheckTransfer(transfer),
   167  	)
   168  
   169  	// now we try again, with a balance above the min amount, but not the whole balance
   170  	e.col.EXPECT().GetPartyVestedRewardAccount(derivedKey, gomock.Any()).Return(&types.Account{Balance: num.NewUint(300)}, nil).Times(1)
   171  	e.assets.EXPECT().Get(gomock.Any()).Times(1).Return(assets.NewAsset(&mockAsset{name: assetNameETH, quantum: num.DecimalFromFloat(100)}), nil)
   172  
   173  	transfer.Amount = num.NewUint(110)
   174  	// try to transfer a small balance, but not the whole balance
   175  	require.NoError(t,
   176  		e.CheckTransfer(transfer),
   177  	)
   178  }