code.vegaprotocol.io/vega@v0.79.0/core/collateral/transfer_funds_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 collateral_test 17 18 import ( 19 "context" 20 "testing" 21 22 "code.vegaprotocol.io/vega/core/types" 23 "code.vegaprotocol.io/vega/libs/num" 24 25 "github.com/golang/mock/gomock" 26 "github.com/stretchr/testify/assert" 27 "github.com/stretchr/testify/require" 28 ) 29 30 func TestCollateralTransferFunds(t *testing.T) { 31 t.Run("invalid number of parameters", testInvalidNumberOfParameters) 32 t.Run("general to general", testTransferFundsFromGeneralToGeneral) 33 t.Run("general to reward pool", testTransferFundsFromGeneralToRewardPool) 34 t.Run("take from general do not distribute", testTakeFromGeneralDoNotDistribute) 35 t.Run("distribute only from pending transfer", testDistributeScheduleFunds) 36 } 37 38 func testDistributeScheduleFunds(t *testing.T) { 39 e := getTestEngine(t) 40 defer e.Finish() 41 42 party1 := "party1" 43 initialBalance := num.NewUint(90) 44 45 e.broker.EXPECT().Send(gomock.Any()).Times(1) 46 pendingTransfersAcc := e.GetPendingTransfersAccount(testMarketAsset) 47 assert.Equal(t, pendingTransfersAcc.Balance, num.UintZero()) 48 49 err := e.UpdateBalance(context.Background(), pendingTransfersAcc.ID, initialBalance) 50 assert.Nil(t, err) 51 52 e.broker.EXPECT().Send(gomock.Any()).Times(4) 53 54 // now we create the transfers: 55 resps, err := e.TransferFunds( 56 context.Background(), 57 []*types.Transfer{ 58 { 59 Owner: party1, 60 Amount: &types.FinancialAmount{ 61 Asset: testMarketAsset, 62 Amount: num.NewUint(90), // we assume the transfer to the other party is 90 63 }, 64 Type: types.TransferTypeTransferFundsDistribute, 65 MinAmount: num.NewUint(90), 66 }, 67 }, 68 // 1 general accounts 69 []types.AccountType{ 70 types.AccountTypeGeneral, 71 }, 72 []string{ 73 "pending-transfer-account-to-party1", 74 }, 75 // no fees, they are paid before 76 []*types.Transfer{}, 77 []types.AccountType{}, 78 ) 79 80 assert.NoError(t, err) 81 assert.Len(t, resps, 1) 82 83 // ensure balances now 84 acc1, err := e.GetPartyGeneralAccount(party1, testMarketAsset) 85 assert.NoError(t, err) 86 assert.Equal(t, acc1.Balance, num.NewUint(90)) 87 88 pendingTransfersAcc = e.GetPendingTransfersAccount(testMarketAsset) 89 assert.NoError(t, err) 90 assert.Equal(t, pendingTransfersAcc.Balance, num.UintZero()) 91 } 92 93 func testTakeFromGeneralDoNotDistribute(t *testing.T) { 94 e := getTestEngine(t) 95 defer e.Finish() 96 97 party1 := "party1" 98 initialBalance := num.NewUint(100) 99 100 // create party1 account + top up 101 // no need to create party2 account, this account 102 // should be created on the go 103 e.broker.EXPECT().Send(gomock.Any()).Times(3) 104 105 p1AccID, err := e.CreatePartyGeneralAccount( 106 context.Background(), party1, testMarketAsset) 107 require.NoError(t, err) 108 109 err = e.UpdateBalance(context.Background(), p1AccID, initialBalance) 110 assert.Nil(t, err) 111 112 e.broker.EXPECT().Send(gomock.Any()).Times(4) 113 114 // now we create the transfers: 115 resps, err := e.TransferFunds( 116 context.Background(), 117 []*types.Transfer{ 118 { 119 Owner: party1, 120 Amount: &types.FinancialAmount{ 121 Asset: testMarketAsset, 122 Amount: num.NewUint(90), // we assume the transfer to the other party is 90 123 }, 124 Type: types.TransferTypeTransferFundsSend, 125 MinAmount: num.NewUint(90), 126 }, 127 }, 128 // 1 general accounts 129 []types.AccountType{ 130 types.AccountTypeGeneral, 131 }, 132 []string{ 133 "party1-to-party2", 134 }, 135 // fee transfer 136 []*types.Transfer{ 137 { 138 Owner: party1, 139 Amount: &types.FinancialAmount{ 140 Asset: testMarketAsset, 141 Amount: num.NewUint(10), // we should have just enough to pay the fee 142 }, 143 Type: types.TransferTypeInfrastructureFeePay, 144 MinAmount: num.NewUint(10), 145 }, 146 }, 147 []types.AccountType{ 148 types.AccountTypeGeneral, // only one account, the general account of party 149 }, 150 ) 151 152 assert.NoError(t, err) 153 assert.Len(t, resps, 2) 154 155 // ensure balances now 156 acc1, err := e.GetPartyGeneralAccount(party1, testMarketAsset) 157 assert.NoError(t, err) 158 assert.Equal(t, acc1.Balance, num.UintZero()) 159 160 pendingTransfersAcc := e.GetPendingTransfersAccount(testMarketAsset) 161 assert.NoError(t, err) 162 assert.Equal(t, pendingTransfersAcc.Balance, num.NewUint(90)) 163 } 164 165 func testTransferFundsFromGeneralToGeneral(t *testing.T) { 166 e := getTestEngine(t) 167 defer e.Finish() 168 169 party1 := "party1" 170 party2 := "party2" 171 initialBalance := num.NewUint(100) 172 173 // create party1 account + top up 174 // no need to create party2 account, this account 175 // should be created on the go 176 e.broker.EXPECT().Send(gomock.Any()).Times(3) 177 178 p1AccID, err := e.CreatePartyGeneralAccount( 179 context.Background(), party1, testMarketAsset) 180 require.NoError(t, err) 181 182 err = e.UpdateBalance(context.Background(), p1AccID, initialBalance) 183 assert.Nil(t, err) 184 185 e.broker.EXPECT().Send(gomock.Any()).Times(8) 186 187 // now we create the transfers: 188 resps, err := e.TransferFunds( 189 context.Background(), 190 []*types.Transfer{ 191 { 192 Owner: party1, 193 Amount: &types.FinancialAmount{ 194 Asset: testMarketAsset, 195 Amount: num.NewUint(90), // we assume the transfer to the other party is 90 196 }, 197 Type: types.TransferTypeTransferFundsSend, 198 MinAmount: num.NewUint(90), 199 }, 200 { 201 Owner: party2, 202 Amount: &types.FinancialAmount{ 203 Asset: testMarketAsset, 204 Amount: num.NewUint(90), 205 }, 206 Type: types.TransferTypeTransferFundsDistribute, 207 MinAmount: num.NewUint(90), 208 }, 209 }, 210 // 2 general accounts 211 []types.AccountType{ 212 types.AccountTypeGeneral, 213 types.AccountTypeGeneral, 214 }, 215 []string{ 216 "party1-to-party2", 217 "party1-to-party2", 218 }, 219 // fee transfer 220 []*types.Transfer{ 221 { 222 Owner: party1, 223 Amount: &types.FinancialAmount{ 224 Asset: testMarketAsset, 225 Amount: num.NewUint(10), // we should have just enough to pay the fee 226 }, 227 Type: types.TransferTypeInfrastructureFeePay, 228 MinAmount: num.NewUint(10), 229 }, 230 }, 231 []types.AccountType{ 232 types.AccountTypeGeneral, // only one account, the general account of party 233 }, 234 ) 235 236 assert.NoError(t, err) 237 assert.Len(t, resps, 3) 238 239 // ensure balances now 240 acc1, err := e.GetPartyGeneralAccount(party1, testMarketAsset) 241 assert.NoError(t, err) 242 assert.Equal(t, acc1.Balance, num.UintZero()) 243 244 acc2, err := e.GetPartyGeneralAccount(party2, testMarketAsset) 245 assert.NoError(t, err) 246 assert.Equal(t, acc2.Balance, num.NewUint(90)) 247 248 pendingTransfersAcc := e.GetPendingTransfersAccount(testMarketAsset) 249 assert.NoError(t, err) 250 assert.Equal(t, pendingTransfersAcc.Balance, num.UintZero()) 251 } 252 253 func testTransferFundsFromGeneralToRewardPool(t *testing.T) { 254 e := getTestEngine(t) 255 defer e.Finish() 256 257 party1 := "party1" 258 initialBalance := num.NewUint(100) 259 260 // create party1 account + top up 261 // no need to create party2 account, this account 262 // should be created on the go 263 e.broker.EXPECT().Send(gomock.Any()).Times(3) 264 265 p1AccID, err := e.CreatePartyGeneralAccount( 266 context.Background(), party1, testMarketAsset) 267 require.NoError(t, err) 268 269 err = e.UpdateBalance(context.Background(), p1AccID, initialBalance) 270 assert.Nil(t, err) 271 272 e.broker.EXPECT().Send(gomock.Any()).Times(6) 273 274 // now we create the transfers: 275 resps, err := e.TransferFunds( 276 context.Background(), 277 []*types.Transfer{ 278 { 279 Owner: party1, 280 Amount: &types.FinancialAmount{ 281 Asset: testMarketAsset, 282 Amount: num.NewUint(90), // we assume the transfer to the other party is 90 283 }, 284 Type: types.TransferTypeTransferFundsSend, 285 MinAmount: num.NewUint(90), 286 }, 287 { 288 Owner: "", 289 Amount: &types.FinancialAmount{ 290 Asset: testMarketAsset, 291 Amount: num.NewUint(90), 292 }, 293 Type: types.TransferTypeTransferFundsDistribute, 294 MinAmount: num.NewUint(90), 295 }, 296 }, 297 // 2 general accounts 298 []types.AccountType{ 299 types.AccountTypeGeneral, 300 types.AccountTypeGlobalReward, 301 }, 302 []string{ 303 "party1-to-reward", 304 "party1-to-reward", 305 }, 306 // fee transfer 307 []*types.Transfer{ 308 { 309 Owner: party1, 310 Amount: &types.FinancialAmount{ 311 Asset: testMarketAsset, 312 Amount: num.NewUint(10), // we should have just enough to pay the fee 313 }, 314 Type: types.TransferTypeInfrastructureFeePay, 315 MinAmount: num.NewUint(10), 316 }, 317 }, 318 []types.AccountType{ 319 types.AccountTypeGeneral, // only one account, the general account of party 320 }, 321 ) 322 323 assert.NoError(t, err) 324 assert.Len(t, resps, 3) 325 326 // ensure balances now 327 acc1, err := e.GetPartyGeneralAccount(party1, testMarketAsset) 328 assert.NoError(t, err) 329 assert.Equal(t, acc1.Balance, num.UintZero()) 330 331 rewardAcc, err := e.GetGlobalRewardAccount(testMarketAsset) 332 assert.NoError(t, err) 333 assert.Equal(t, rewardAcc.Balance, num.NewUint(90)) 334 335 pendingTransfersAcc := e.GetPendingTransfersAccount(testMarketAsset) 336 assert.NoError(t, err) 337 assert.Equal(t, pendingTransfersAcc.Balance, num.UintZero()) 338 } 339 340 func testInvalidNumberOfParameters(t *testing.T) { 341 e := getTestEngine(t) 342 defer e.Finish() 343 344 assert.Panics(t, func() { 345 e.TransferFunds( 346 context.Background(), 347 make([]*types.Transfer, 3), 348 make([]types.AccountType, 2), 349 make([]string, 3), 350 make([]*types.Transfer, 1), 351 make([]types.AccountType, 1), 352 ) 353 }) 354 assert.Panics(t, func() { 355 e.TransferFunds( 356 context.Background(), 357 make([]*types.Transfer, 3), 358 make([]types.AccountType, 3), 359 make([]string, 1), 360 make([]*types.Transfer, 1), 361 make([]types.AccountType, 1), 362 ) 363 }) 364 assert.Panics(t, func() { 365 e.TransferFunds( 366 context.Background(), 367 make([]*types.Transfer, 3), 368 make([]types.AccountType, 3), 369 make([]string, 3), 370 make([]*types.Transfer, 2), 371 make([]types.AccountType, 1), 372 ) 373 }) 374 }