@@ -620,7 +620,56 @@ contract PionexContractTest is StrategySharedSetup {
620
620
userProxy.toLimitOrder (payload);
621
621
}
622
622
623
- function testFullyFillByTrader () public {
623
+ function testCannotFullyFillByTraderWithWorseTakerTokenAmountDueToFee () public {
624
+ IPionexContract.TraderParams memory traderParams = DEFAULT_TRADER_PARAMS;
625
+ traderParams.gasFeeFactor = 50 ; // gasFeeFactor: 0.5%
626
+ traderParams.pionexStrategyFeeFactor = 250 ; // pionexStrategyFeeFactor: 2.5%
627
+ traderParams.pionexSig = _signFill (pionexPrivateKey, DEFAULT_FILL, SignatureValidator.SignatureType.EIP712);
628
+
629
+ bytes memory payload = _genFillByTraderPayload (DEFAULT_ORDER, DEFAULT_ORDER_MAKER_SIG, traderParams, DEFAULT_CRD_PARAMS);
630
+ vm.expectRevert ("PionexContract: pionex token amount not enough " );
631
+ vm.prank (pionex, pionex); // Only EOA
632
+ userProxy.toLimitOrder (payload);
633
+ }
634
+
635
+ function testFullyFillByTraderWithNoFee () public {
636
+ BalanceSnapshot.Snapshot memory pionexTakerAsset = BalanceSnapshot.take (pionex, address (DEFAULT_ORDER.pionexToken));
637
+ BalanceSnapshot.Snapshot memory receiverMakerAsset = BalanceSnapshot.take (receiver, address (DEFAULT_ORDER.userToken));
638
+ BalanceSnapshot.Snapshot memory userTakerAsset = BalanceSnapshot.take (user, address (DEFAULT_ORDER.pionexToken));
639
+ BalanceSnapshot.Snapshot memory userMakerAsset = BalanceSnapshot.take (user, address (DEFAULT_ORDER.userToken));
640
+ BalanceSnapshot.Snapshot memory fcMakerAsset = BalanceSnapshot.take (feeCollector, address (DEFAULT_ORDER.userToken));
641
+ BalanceSnapshot.Snapshot memory fcTakerAsset = BalanceSnapshot.take (feeCollector, address (DEFAULT_ORDER.pionexToken));
642
+
643
+ bytes memory payload = _genFillByTraderPayload (DEFAULT_ORDER, DEFAULT_ORDER_MAKER_SIG, DEFAULT_TRADER_PARAMS, DEFAULT_CRD_PARAMS);
644
+ vm.expectEmit (true , true , true , true );
645
+ emit LimitOrderFilledByTrader (
646
+ DEFAULT_ORDER_HASH,
647
+ DEFAULT_ORDER.user,
648
+ pionex,
649
+ getEIP712Hash (pionexContract.EIP712_DOMAIN_SEPARATOR (), PionexContractLibEIP712._getAllowFillStructHash (DEFAULT_ALLOW_FILL)),
650
+ DEFAULT_TRADER_PARAMS.recipient,
651
+ IPionexContract.FillReceipt (
652
+ address (DEFAULT_ORDER.userToken),
653
+ address (DEFAULT_ORDER.pionexToken),
654
+ DEFAULT_ORDER.userTokenAmount,
655
+ DEFAULT_ORDER.minPionexTokenAmount,
656
+ 0 , // remainingUserTokenAmount should be zero after order fully filled
657
+ 0 , // tokenlonFee = 0
658
+ 0 // pionexStrategyFee = 0
659
+ )
660
+ );
661
+ vm.prank (pionex, pionex); // Only EOA
662
+ userProxy.toLimitOrder (payload);
663
+
664
+ pionexTakerAsset.assertChange (- int256 (DEFAULT_ORDER.minPionexTokenAmount));
665
+ receiverMakerAsset.assertChange (int256 (DEFAULT_ORDER.userTokenAmount));
666
+ userTakerAsset.assertChange (int256 (DEFAULT_ORDER.minPionexTokenAmount));
667
+ userMakerAsset.assertChange (- int256 (DEFAULT_ORDER.userTokenAmount));
668
+ fcMakerAsset.assertChange (0 );
669
+ fcTakerAsset.assertChange (0 );
670
+ }
671
+
672
+ function testFullyFillByTraderWithAddedTokenlonFee () public {
624
673
BalanceSnapshot.Snapshot memory pionexTakerAsset = BalanceSnapshot.take (pionex, address (DEFAULT_ORDER.pionexToken));
625
674
BalanceSnapshot.Snapshot memory receiverMakerAsset = BalanceSnapshot.take (receiver, address (DEFAULT_ORDER.userToken));
626
675
BalanceSnapshot.Snapshot memory userTakerAsset = BalanceSnapshot.take (user, address (DEFAULT_ORDER.pionexToken));
@@ -635,38 +684,102 @@ contract PionexContractTest is StrategySharedSetup {
635
684
pionexContract.activateFactors ();
636
685
vm.stopPrank ();
637
686
687
+ PionexContractLibEIP712.Fill memory fill = DEFAULT_FILL;
688
+ // Increase pionex token amount so the pionexToken/userToken ratio is better than order's pionexToken/userToken ratio
689
+ // to account for tokenlon fee
690
+ fill.pionexTokenAmount = DEFAULT_FILL.pionexTokenAmount.mul (115 ).div (100 ); // 15% more
691
+
692
+ IPionexContract.TraderParams memory traderParams = DEFAULT_TRADER_PARAMS;
693
+ traderParams.pionexTokenAmount = fill.pionexTokenAmount;
694
+ traderParams.pionexSig = _signFill (pionexPrivateKey, fill, SignatureValidator.SignatureType.EIP712);
695
+
696
+ PionexContractLibEIP712.AllowFill memory allowFill = DEFAULT_ALLOW_FILL;
697
+ allowFill.fillAmount = traderParams.pionexTokenAmount;
698
+
699
+ IPionexContract.CoordinatorParams memory crdParams = DEFAULT_CRD_PARAMS;
700
+ crdParams.sig = _signAllowFill (coordinatorPrivateKey, allowFill, SignatureValidator.SignatureType.EIP712);
701
+
702
+ bytes memory payload = _genFillByTraderPayload (DEFAULT_ORDER, DEFAULT_ORDER_MAKER_SIG, traderParams, crdParams);
703
+ vm.expectEmit (true , true , true , true );
704
+ emit LimitOrderFilledByTrader (
705
+ DEFAULT_ORDER_HASH,
706
+ DEFAULT_ORDER.user,
707
+ pionex,
708
+ getEIP712Hash (pionexContract.EIP712_DOMAIN_SEPARATOR (), PionexContractLibEIP712._getAllowFillStructHash (allowFill)),
709
+ DEFAULT_TRADER_PARAMS.recipient,
710
+ IPionexContract.FillReceipt (
711
+ address (DEFAULT_ORDER.userToken),
712
+ address (DEFAULT_ORDER.pionexToken),
713
+ DEFAULT_ORDER.userTokenAmount,
714
+ traderParams.pionexTokenAmount,
715
+ 0 , // remainingUserTokenAmount should be zero after order fully filled
716
+ traderParams.pionexTokenAmount.div (10 ), // tokenlonFee = 10% pionexTokenAmount
717
+ 0 // pionexStrategyFee = 0
718
+ )
719
+ );
720
+ vm.prank (pionex, pionex); // Only EOA
721
+ userProxy.toLimitOrder (payload);
722
+
723
+ pionexTakerAsset.assertChange (- int256 (traderParams.pionexTokenAmount));
724
+ receiverMakerAsset.assertChange (int256 (DEFAULT_ORDER.userTokenAmount));
725
+ userTakerAsset.assertChange (int256 (traderParams.pionexTokenAmount.mul (9 ).div (10 ))); // 10% fee for Tokenlon
726
+ userMakerAsset.assertChange (- int256 (DEFAULT_ORDER.userTokenAmount));
727
+ fcMakerAsset.assertChange (0 );
728
+ fcTakerAsset.assertChange (int256 (traderParams.pionexTokenAmount.div (10 )));
729
+ }
730
+
731
+ function testFullyFillByTraderWithAddedGasFeeAndStrategyFee () public {
732
+ BalanceSnapshot.Snapshot memory pionexTakerAsset = BalanceSnapshot.take (pionex, address (DEFAULT_ORDER.pionexToken));
733
+ BalanceSnapshot.Snapshot memory receiverMakerAsset = BalanceSnapshot.take (receiver, address (DEFAULT_ORDER.userToken));
734
+ BalanceSnapshot.Snapshot memory userTakerAsset = BalanceSnapshot.take (user, address (DEFAULT_ORDER.pionexToken));
735
+ BalanceSnapshot.Snapshot memory userMakerAsset = BalanceSnapshot.take (user, address (DEFAULT_ORDER.userToken));
736
+ BalanceSnapshot.Snapshot memory fcMakerAsset = BalanceSnapshot.take (feeCollector, address (DEFAULT_ORDER.userToken));
737
+ BalanceSnapshot.Snapshot memory fcTakerAsset = BalanceSnapshot.take (feeCollector, address (DEFAULT_ORDER.pionexToken));
738
+
739
+ PionexContractLibEIP712.Fill memory fill = DEFAULT_FILL;
740
+ // Increase pionex token amount so the pionexToken/userToken ratio is better than order's pionexToken/userToken ratio
741
+ // to account for gas fee and pionex strategy fee
742
+ fill.pionexTokenAmount = DEFAULT_FILL.pionexTokenAmount.mul (11 ).div (10 ); // 10% more
743
+
638
744
IPionexContract.TraderParams memory traderParams = DEFAULT_TRADER_PARAMS;
639
745
traderParams.gasFeeFactor = 50 ; // gasFeeFactor: 0.5%
640
746
traderParams.pionexStrategyFeeFactor = 250 ; // pionexStrategyFeeFactor: 2.5%
641
- traderParams.pionexSig = _signFill (pionexPrivateKey, DEFAULT_FILL, SignatureValidator.SignatureType.EIP712);
747
+ traderParams.pionexTokenAmount = fill.pionexTokenAmount;
748
+ traderParams.pionexSig = _signFill (pionexPrivateKey, fill, SignatureValidator.SignatureType.EIP712);
642
749
643
- bytes memory payload = _genFillByTraderPayload (DEFAULT_ORDER, DEFAULT_ORDER_MAKER_SIG, traderParams, DEFAULT_CRD_PARAMS);
750
+ PionexContractLibEIP712.AllowFill memory allowFill = DEFAULT_ALLOW_FILL;
751
+ allowFill.fillAmount = traderParams.pionexTokenAmount;
752
+
753
+ IPionexContract.CoordinatorParams memory crdParams = DEFAULT_CRD_PARAMS;
754
+ crdParams.sig = _signAllowFill (coordinatorPrivateKey, allowFill, SignatureValidator.SignatureType.EIP712);
755
+
756
+ bytes memory payload = _genFillByTraderPayload (DEFAULT_ORDER, DEFAULT_ORDER_MAKER_SIG, traderParams, crdParams);
644
757
vm.expectEmit (true , true , true , true );
645
758
emit LimitOrderFilledByTrader (
646
759
DEFAULT_ORDER_HASH,
647
760
DEFAULT_ORDER.user,
648
761
pionex,
649
- getEIP712Hash (pionexContract.EIP712_DOMAIN_SEPARATOR (), PionexContractLibEIP712._getAllowFillStructHash (DEFAULT_ALLOW_FILL )),
762
+ getEIP712Hash (pionexContract.EIP712_DOMAIN_SEPARATOR (), PionexContractLibEIP712._getAllowFillStructHash (allowFill )),
650
763
DEFAULT_TRADER_PARAMS.recipient,
651
764
IPionexContract.FillReceipt (
652
765
address (DEFAULT_ORDER.userToken),
653
766
address (DEFAULT_ORDER.pionexToken),
654
767
DEFAULT_ORDER.userTokenAmount,
655
- DEFAULT_ORDER.minPionexTokenAmount ,
768
+ traderParams.pionexTokenAmount ,
656
769
0 , // remainingUserTokenAmount should be zero after order fully filled
657
- DEFAULT_ORDER.minPionexTokenAmount. mul ( 10 ). div ( 100 ) , // tokenlonFee = 10% pionexTokenAmount
658
- DEFAULT_ORDER.minPionexTokenAmount .mul (3 ).div (100 ) // pionexStrategyFee = 0.5% + 2.5% = 3% pionexTokenAmount
770
+ 0 , // tokenlonFee = 0
771
+ traderParams.pionexTokenAmount .mul (3 ).div (100 ) // pionexStrategyFee = 0.5% + 2.5% = 3% pionexTokenAmount
659
772
)
660
773
);
661
774
vm.prank (pionex, pionex); // Only EOA
662
775
userProxy.toLimitOrder (payload);
663
776
664
- pionexTakerAsset.assertChange (- int256 (DEFAULT_ORDER.minPionexTokenAmount .mul (97 ).div (100 ))); // 3% fee for Pionex is deducted from pionexTokenAmount directly
777
+ pionexTakerAsset.assertChange (- int256 (traderParams.pionexTokenAmount .mul (97 ).div (100 ))); // 3% fee for Pionex is deducted from pionexTokenAmount directly
665
778
receiverMakerAsset.assertChange (int256 (DEFAULT_ORDER.userTokenAmount));
666
- userTakerAsset.assertChange (int256 (DEFAULT_ORDER.minPionexTokenAmount .mul (87 ).div (100 ))); // 10% fee for Tokenlon and 3% fee for Pionex
779
+ userTakerAsset.assertChange (int256 (traderParams.pionexTokenAmount .mul (97 ).div (100 ))); // 3% fee for Pionex
667
780
userMakerAsset.assertChange (- int256 (DEFAULT_ORDER.userTokenAmount));
668
781
fcMakerAsset.assertChange (0 );
669
- fcTakerAsset.assertChange (int256 (DEFAULT_ORDER.minPionexTokenAmount. mul ( 10 ). div ( 100 )) );
782
+ fcTakerAsset.assertChange (0 );
670
783
}
671
784
672
785
function testFullyFillByTraderWithBetterTakerMakerTokenRatio () public {
0 commit comments