github.com/XinFinOrg/XDPoSChain@v1.6.0/XDCx/order_processor_test.go (about) 1 package XDCx 2 3 import ( 4 "github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate" 5 "github.com/XinFinOrg/XDPoSChain/common" 6 "github.com/XinFinOrg/XDPoSChain/core/rawdb" 7 "math/big" 8 "reflect" 9 "testing" 10 ) 11 12 func Test_getCancelFeeV1(t *testing.T) { 13 type CancelFeeArg struct { 14 baseTokenDecimal *big.Int 15 feeRate *big.Int 16 order *tradingstate.OrderItem 17 } 18 tests := []struct { 19 name string 20 args CancelFeeArg 21 want *big.Int 22 }{ 23 // zero fee test: SELL 24 { 25 "zero fee getCancelFeeV1: SELL", 26 CancelFeeArg{ 27 baseTokenDecimal: common.Big1, 28 feeRate: common.Big0, 29 order: &tradingstate.OrderItem{ 30 Quantity: new(big.Int).SetUint64(10000), 31 Side: tradingstate.Ask, 32 }, 33 }, 34 common.Big0, 35 }, 36 37 // zero fee test: BUY 38 { 39 "zero fee getCancelFeeV1: BUY", 40 CancelFeeArg{ 41 baseTokenDecimal: common.Big1, 42 feeRate: common.Big0, 43 order: &tradingstate.OrderItem{ 44 Quantity: new(big.Int).SetUint64(10000), 45 Price: new(big.Int).SetUint64(1), 46 Side: tradingstate.Bid, 47 }, 48 }, 49 common.Big0, 50 }, 51 52 // test getCancelFee: SELL 53 { 54 "test getCancelFeeV1:: SELL", 55 CancelFeeArg{ 56 baseTokenDecimal: common.Big1, 57 feeRate: new(big.Int).SetUint64(10), // 10/10000= 0.1% 58 order: &tradingstate.OrderItem{ 59 Quantity: new(big.Int).SetUint64(10000), 60 Side: tradingstate.Ask, 61 }, 62 }, 63 common.Big1, 64 }, 65 66 // test getCancelFee:: BUY 67 { 68 "test getCancelFeeV1:: BUY", 69 CancelFeeArg{ 70 baseTokenDecimal: common.Big1, 71 feeRate: new(big.Int).SetUint64(10), // 10/10000= 0.1% 72 order: &tradingstate.OrderItem{ 73 Quantity: new(big.Int).SetUint64(10000), 74 Price: new(big.Int).SetUint64(1), 75 Side: tradingstate.Bid, 76 }, 77 }, 78 common.Big1, 79 }, 80 } 81 for _, tt := range tests { 82 t.Run(tt.name, func(t *testing.T) { 83 if got := getCancelFeeV1(tt.args.baseTokenDecimal, tt.args.feeRate, tt.args.order); !reflect.DeepEqual(got, tt.want) { 84 t.Errorf("getCancelFeeV1() = %v, quantity %v", got, tt.want) 85 } 86 }) 87 } 88 } 89 90 func Test_getCancelFee(t *testing.T) { 91 XDCx := New(&DefaultConfig) 92 db := rawdb.NewMemoryDatabase() 93 stateCache := tradingstate.NewDatabase(db) 94 tradingStateDb, _ := tradingstate.New(common.Hash{}, stateCache) 95 96 testTokenA := common.HexToAddress("0x1000000000000000000000000000000000000002") 97 testTokenB := common.HexToAddress("0x1100000000000000000000000000000000000003") 98 // set decimal 99 // tokenA has decimal 10^18 100 XDCx.SetTokenDecimal(testTokenA, common.BasePrice) 101 // tokenB has decimal 10^8 102 tokenBDecimal := new(big.Int).Exp(big.NewInt(10), big.NewInt(8), nil) 103 XDCx.SetTokenDecimal(testTokenB, tokenBDecimal) 104 105 // set tokenAPrice = 1 XDC 106 tradingStateDb.SetMediumPriceBeforeEpoch(tradingstate.GetTradingOrderBookHash(testTokenA, common.HexToAddress(common.XDCNativeAddress)), common.BasePrice) 107 // set tokenBPrice = 1 XDC 108 tradingStateDb.SetMediumPriceBeforeEpoch(tradingstate.GetTradingOrderBookHash(common.HexToAddress(common.XDCNativeAddress), testTokenB), tokenBDecimal) 109 110 type CancelFeeArg struct { 111 feeRate *big.Int 112 order *tradingstate.OrderItem 113 } 114 tests := []struct { 115 name string 116 args CancelFeeArg 117 want *big.Int 118 }{ 119 120 // BASE: testTokenA, 121 // QUOTE: XDC 122 123 // zero fee test: SELL 124 { 125 "TokenA/XDC zero fee test: SELL", 126 CancelFeeArg{ 127 feeRate: common.Big0, 128 order: &tradingstate.OrderItem{ 129 BaseToken: testTokenA, 130 QuoteToken: common.HexToAddress(common.XDCNativeAddress), 131 Quantity: new(big.Int).SetUint64(10000), 132 Side: tradingstate.Ask, 133 }, 134 }, 135 common.Big0, 136 }, 137 138 // zero fee test: BUY 139 { 140 "TokenA/XDC zero fee test: BUY", 141 CancelFeeArg{ 142 feeRate: common.Big0, 143 order: &tradingstate.OrderItem{ 144 BaseToken: testTokenA, 145 QuoteToken: common.HexToAddress(common.XDCNativeAddress), 146 Quantity: new(big.Int).SetUint64(10000), 147 Side: tradingstate.Bid, 148 }, 149 }, 150 common.Big0, 151 }, 152 153 // test getCancelFee: SELL 154 { 155 "TokenA/XDC test getCancelFee:: SELL", 156 CancelFeeArg{ 157 feeRate: new(big.Int).SetUint64(10), // 10/10000= 0.1% 158 order: &tradingstate.OrderItem{ 159 BaseToken: common.HexToAddress(common.XDCNativeAddress), 160 QuoteToken: testTokenA, 161 Quantity: new(big.Int).SetUint64(10000), 162 Side: tradingstate.Ask, 163 }, 164 }, 165 common.RelayerCancelFee, 166 }, 167 168 // test getCancelFee:: BUY 169 { 170 "TokenA/XDC test getCancelFee:: BUY", 171 CancelFeeArg{ 172 feeRate: new(big.Int).SetUint64(10), // 10/10000= 0.1% 173 order: &tradingstate.OrderItem{ 174 Quantity: new(big.Int).SetUint64(10000), 175 BaseToken: common.HexToAddress(common.XDCNativeAddress), 176 QuoteToken: testTokenA, 177 Side: tradingstate.Bid, 178 }, 179 }, 180 common.RelayerCancelFee, 181 }, 182 183 // BASE: XDC 184 // QUOTE: testTokenA 185 // zero fee test: SELL 186 { 187 "XDC/TokenA zero fee test: SELL", 188 CancelFeeArg{ 189 feeRate: common.Big0, 190 order: &tradingstate.OrderItem{ 191 BaseToken: common.HexToAddress(common.XDCNativeAddress), 192 QuoteToken: testTokenA, 193 Quantity: new(big.Int).SetUint64(10000), 194 Side: tradingstate.Ask, 195 }, 196 }, 197 common.Big0, 198 }, 199 200 // zero fee test: BUY 201 { 202 "XDC/TokenA zero fee test: BUY", 203 CancelFeeArg{ 204 feeRate: common.Big0, 205 order: &tradingstate.OrderItem{ 206 BaseToken: common.HexToAddress(common.XDCNativeAddress), 207 QuoteToken: testTokenA, 208 Quantity: new(big.Int).SetUint64(10000), 209 Side: tradingstate.Bid, 210 }, 211 }, 212 common.Big0, 213 }, 214 215 // test getCancelFee: SELL 216 { 217 "XDC/TokenA test getCancelFee:: SELL", 218 CancelFeeArg{ 219 feeRate: new(big.Int).SetUint64(10), // 10/10000= 0.1% 220 order: &tradingstate.OrderItem{ 221 BaseToken: common.HexToAddress(common.XDCNativeAddress), 222 QuoteToken: testTokenA, 223 Quantity: new(big.Int).SetUint64(10000), 224 Side: tradingstate.Ask, 225 }, 226 }, 227 common.RelayerCancelFee, 228 }, 229 230 // test getCancelFee:: BUY 231 { 232 "XDC/TokenA test getCancelFee:: BUY", 233 CancelFeeArg{ 234 feeRate: new(big.Int).SetUint64(10), // 10/10000= 0.1% 235 order: &tradingstate.OrderItem{ 236 Quantity: new(big.Int).SetUint64(10000), 237 BaseToken: common.HexToAddress(common.XDCNativeAddress), 238 QuoteToken: testTokenA, 239 Side: tradingstate.Bid, 240 }, 241 }, 242 common.RelayerCancelFee, 243 }, 244 245 // BASE: testTokenB 246 // QUOTE: testTokenA 247 // zero fee test: SELL 248 { 249 "TokenB/TokenA zero fee test: SELL", 250 CancelFeeArg{ 251 feeRate: common.Big0, 252 order: &tradingstate.OrderItem{ 253 BaseToken: testTokenB, 254 QuoteToken: testTokenA, 255 Quantity: new(big.Int).SetUint64(10000), 256 Side: tradingstate.Ask, 257 }, 258 }, 259 common.Big0, 260 }, 261 262 // zero fee test: BUY 263 { 264 "TokenB/TokenA zero fee test: BUY", 265 CancelFeeArg{ 266 feeRate: common.Big0, 267 order: &tradingstate.OrderItem{ 268 BaseToken: testTokenB, 269 QuoteToken: testTokenA, 270 Quantity: new(big.Int).SetUint64(10000), 271 Side: tradingstate.Bid, 272 }, 273 }, 274 common.Big0, 275 }, 276 277 // test getCancelFee: SELL 278 { 279 "TokenB/TokenA test getCancelFee:: SELL", 280 CancelFeeArg{ 281 feeRate: new(big.Int).SetUint64(10), // 10/10000= 0.1% 282 order: &tradingstate.OrderItem{ 283 BaseToken: testTokenB, 284 QuoteToken: testTokenA, 285 Quantity: new(big.Int).SetUint64(10000), 286 Side: tradingstate.Ask, 287 }, 288 }, 289 new(big.Int).Exp(big.NewInt(10), big.NewInt(4), nil), 290 }, 291 292 // test getCancelFee:: BUY 293 { 294 "TokenB/TokenA test getCancelFee:: BUY", 295 CancelFeeArg{ 296 feeRate: new(big.Int).SetUint64(10), // 10/10000= 0.1% 297 order: &tradingstate.OrderItem{ 298 Quantity: new(big.Int).SetUint64(10000), 299 BaseToken: testTokenB, 300 QuoteToken: testTokenA, 301 Side: tradingstate.Bid, 302 }, 303 }, 304 common.RelayerCancelFee, 305 }, 306 } 307 for _, tt := range tests { 308 t.Run(tt.name, func(t *testing.T) { 309 if got, _ := XDCx.getCancelFee(nil, nil, tradingStateDb, tt.args.order, tt.args.feeRate); !reflect.DeepEqual(got, tt.want) { 310 t.Errorf("getCancelFee() = %v, quantity %v", got, tt.want) 311 } 312 }) 313 } 314 315 // testcase: can't get price of token in XDC 316 testTokenC := common.HexToAddress("0x1200000000000000000000000000000000000004") 317 XDCx.SetTokenDecimal(testTokenC, big.NewInt(1)) 318 tokenCOrder := CancelFeeArg{ 319 feeRate: new(big.Int).SetUint64(10), // 10/10000= 0.1% 320 order: &tradingstate.OrderItem{ 321 Quantity: new(big.Int).SetUint64(10000), 322 BaseToken: testTokenC, 323 QuoteToken: testTokenA, 324 Side: tradingstate.Ask, 325 }, 326 } 327 if fee, _ := XDCx.getCancelFee(nil, nil, tradingStateDb, tokenCOrder.order, tokenCOrder.feeRate); fee != nil && fee.Sign() != 0 { 328 t.Errorf("getCancelFee() = %v, want %v", fee, common.Big0) 329 } 330 331 // testcase: invalid token decimal 332 testTokenD := common.HexToAddress("0x1300000000000000000000000000000000000005") 333 XDCx.SetTokenDecimal(testTokenD, big.NewInt(0)) 334 tokenDOrder := CancelFeeArg{ 335 feeRate: new(big.Int).SetUint64(10), // 10/10000= 0.1% 336 order: &tradingstate.OrderItem{ 337 Quantity: new(big.Int).SetUint64(10000), 338 BaseToken: testTokenD, 339 QuoteToken: testTokenA, 340 Side: tradingstate.Ask, 341 }, 342 } 343 if fee, _ := XDCx.getCancelFee(nil, nil, tradingStateDb, tokenDOrder.order, tokenDOrder.feeRate); fee != nil && fee.Sign() != 0 { 344 t.Errorf("getCancelFee() = %v, want %v", fee, common.Big0) 345 } 346 347 } 348 349 func TestGetTradeQuantity(t *testing.T) { 350 type GetTradeQuantityArg struct { 351 takerSide string 352 takerFeeRate *big.Int 353 takerBalance *big.Int 354 makerPrice *big.Int 355 makerFeeRate *big.Int 356 makerBalance *big.Int 357 baseTokenDecimal *big.Int 358 quantityToTrade *big.Int 359 } 360 tests := []struct { 361 name string 362 args GetTradeQuantityArg 363 quantity *big.Int 364 rejectMaker bool 365 }{ 366 { 367 "BUY: feeRate = 0, price 1, quantity 1000, taker balance 1000, maker balance 1000", 368 GetTradeQuantityArg{ 369 takerSide: tradingstate.Bid, 370 takerFeeRate: common.Big0, 371 takerBalance: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 372 makerPrice: common.BasePrice, 373 makerFeeRate: common.Big0, 374 makerBalance: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 375 baseTokenDecimal: common.BasePrice, 376 quantityToTrade: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 377 }, 378 new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 379 false, 380 }, 381 { 382 "BUY: feeRate = 0, price 1, quantity 1000, taker balance 1000, maker balance 900 -> reject maker", 383 GetTradeQuantityArg{ 384 takerSide: tradingstate.Bid, 385 takerFeeRate: common.Big0, 386 takerBalance: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 387 makerPrice: common.BasePrice, 388 makerFeeRate: common.Big0, 389 makerBalance: new(big.Int).Mul(big.NewInt(900), common.BasePrice), 390 baseTokenDecimal: common.BasePrice, 391 quantityToTrade: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 392 }, 393 new(big.Int).Mul(big.NewInt(900), common.BasePrice), 394 true, 395 }, 396 { 397 "BUY: feeRate = 0, price 1, quantity 1000, taker balance 900, maker balance 1000 -> reject taker", 398 GetTradeQuantityArg{ 399 takerSide: tradingstate.Bid, 400 takerFeeRate: common.Big0, 401 takerBalance: new(big.Int).Mul(big.NewInt(900), common.BasePrice), 402 makerPrice: common.BasePrice, 403 makerFeeRate: common.Big0, 404 makerBalance: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 405 baseTokenDecimal: common.BasePrice, 406 quantityToTrade: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 407 }, 408 new(big.Int).Mul(big.NewInt(900), common.BasePrice), 409 false, 410 }, 411 { 412 "BUY: feeRate = 0, price 1, quantity 1000, taker balance 0, maker balance 1000 -> reject taker", 413 GetTradeQuantityArg{ 414 takerSide: tradingstate.Bid, 415 takerFeeRate: common.Big0, 416 takerBalance: common.Big0, 417 makerPrice: common.BasePrice, 418 makerFeeRate: common.Big0, 419 makerBalance: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 420 baseTokenDecimal: common.BasePrice, 421 quantityToTrade: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 422 }, 423 common.Big0, 424 false, 425 }, 426 { 427 "BUY: feeRate = 0, price 1, quantity 1000, taker balance 0, maker balance 0 -> reject both taker", 428 GetTradeQuantityArg{ 429 takerSide: tradingstate.Bid, 430 takerFeeRate: common.Big0, 431 takerBalance: common.Big0, 432 makerPrice: common.BasePrice, 433 makerFeeRate: common.Big0, 434 makerBalance: common.Big0, 435 baseTokenDecimal: common.BasePrice, 436 quantityToTrade: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 437 }, 438 common.Big0, 439 false, 440 }, 441 { 442 "BUY: feeRate = 0, price 1, quantity 1000, taker balance 500, maker balance 100 -> reject both taker, maker", 443 GetTradeQuantityArg{ 444 takerSide: tradingstate.Bid, 445 takerFeeRate: common.Big0, 446 takerBalance: new(big.Int).Mul(big.NewInt(500), common.BasePrice), 447 makerPrice: common.BasePrice, 448 makerFeeRate: common.Big0, 449 makerBalance: new(big.Int).Mul(big.NewInt(100), common.BasePrice), 450 baseTokenDecimal: common.BasePrice, 451 quantityToTrade: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 452 }, 453 new(big.Int).Mul(big.NewInt(100), common.BasePrice), 454 true, 455 }, 456 457 { 458 "SELL: feeRate = 0, price 1, quantity 1000, taker balance 1000, maker balance 1000", 459 GetTradeQuantityArg{ 460 takerSide: tradingstate.Ask, 461 takerFeeRate: common.Big0, 462 takerBalance: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 463 makerPrice: common.BasePrice, 464 makerFeeRate: common.Big0, 465 makerBalance: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 466 baseTokenDecimal: common.BasePrice, 467 quantityToTrade: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 468 }, 469 new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 470 false, 471 }, 472 { 473 "SELL: feeRate = 0, price 1, quantity 1000, taker balance 1000, maker balance 900 -> reject maker", 474 GetTradeQuantityArg{ 475 takerSide: tradingstate.Ask, 476 takerFeeRate: common.Big0, 477 takerBalance: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 478 makerPrice: common.BasePrice, 479 makerFeeRate: common.Big0, 480 makerBalance: new(big.Int).Mul(big.NewInt(900), common.BasePrice), 481 baseTokenDecimal: common.BasePrice, 482 quantityToTrade: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 483 }, 484 new(big.Int).Mul(big.NewInt(900), common.BasePrice), 485 true, 486 }, 487 { 488 "SELL: feeRate = 0, price 1, quantity 1000, taker balance 900, maker balance 1000 -> reject taker", 489 GetTradeQuantityArg{ 490 takerSide: tradingstate.Ask, 491 takerFeeRate: common.Big0, 492 takerBalance: new(big.Int).Mul(big.NewInt(900), common.BasePrice), 493 makerPrice: common.BasePrice, 494 makerFeeRate: common.Big0, 495 makerBalance: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 496 baseTokenDecimal: common.BasePrice, 497 quantityToTrade: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 498 }, 499 new(big.Int).Mul(big.NewInt(900), common.BasePrice), 500 false, 501 }, 502 { 503 "SELL: feeRate = 0, price 1, quantity 1000, taker balance 0, maker balance 1000 -> reject taker", 504 GetTradeQuantityArg{ 505 takerSide: tradingstate.Ask, 506 takerFeeRate: common.Big0, 507 takerBalance: common.Big0, 508 makerPrice: common.BasePrice, 509 makerFeeRate: common.Big0, 510 makerBalance: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 511 baseTokenDecimal: common.BasePrice, 512 quantityToTrade: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 513 }, 514 common.Big0, 515 false, 516 }, 517 { 518 "SELL: feeRate = 0, price 1, quantity 1000, taker balance 0, maker balance 0 -> reject maker", 519 GetTradeQuantityArg{ 520 takerSide: tradingstate.Ask, 521 takerFeeRate: common.Big0, 522 takerBalance: common.Big0, 523 makerPrice: common.BasePrice, 524 makerFeeRate: common.Big0, 525 makerBalance: common.Big0, 526 baseTokenDecimal: common.BasePrice, 527 quantityToTrade: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 528 }, 529 common.Big0, 530 true, 531 }, 532 { 533 "SELL: feeRate = 0, price 1, quantity 1000, taker balance 500, maker balance 100 -> reject both taker, maker", 534 GetTradeQuantityArg{ 535 takerSide: tradingstate.Ask, 536 takerFeeRate: common.Big0, 537 takerBalance: new(big.Int).Mul(big.NewInt(500), common.BasePrice), 538 makerPrice: common.BasePrice, 539 makerFeeRate: common.Big0, 540 makerBalance: new(big.Int).Mul(big.NewInt(100), common.BasePrice), 541 baseTokenDecimal: common.BasePrice, 542 quantityToTrade: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 543 }, 544 new(big.Int).Mul(big.NewInt(100), common.BasePrice), 545 true, 546 }, 547 { 548 "SELL: feeRate = 0, price 1, quantity 1000, taker balance 0, maker balance 100 -> reject both taker, maker", 549 GetTradeQuantityArg{ 550 takerSide: tradingstate.Ask, 551 takerFeeRate: common.Big0, 552 takerBalance: common.Big0, 553 makerPrice: common.BasePrice, 554 makerFeeRate: common.Big0, 555 makerBalance: new(big.Int).Mul(big.NewInt(100), common.BasePrice), 556 baseTokenDecimal: common.BasePrice, 557 quantityToTrade: new(big.Int).Mul(big.NewInt(1000), common.BasePrice), 558 }, 559 common.Big0, 560 false, 561 }, 562 } 563 for _, tt := range tests { 564 t.Run(tt.name, func(t *testing.T) { 565 got, got1 := GetTradeQuantity(tt.args.takerSide, tt.args.takerFeeRate, tt.args.takerBalance, tt.args.makerPrice, tt.args.makerFeeRate, tt.args.makerBalance, tt.args.baseTokenDecimal, tt.args.quantityToTrade) 566 if !reflect.DeepEqual(got, tt.quantity) { 567 t.Errorf("GetTradeQuantity() got = %v, quantity %v", got, tt.quantity) 568 } 569 if got1 != tt.rejectMaker { 570 t.Errorf("GetTradeQuantity() got1 = %v, quantity %v", got1, tt.rejectMaker) 571 } 572 }) 573 } 574 }