@@ -566,6 +566,177 @@ contract CrosschainVaultDebtTest is CrosschainVaultTestBase {
566566 );
567567 vault.repay (DEFAULT_PATH, DEFAULT_CHANNEL_ID, BASE_TOKEN, 100001 );
568568 }
569+
570+ function testRepayFullDebt () public {
571+ _setupCounterparty ();
572+ _fundVault (10000000 );
573+
574+ TokenOrderV2 memory order = _createTokenOrder (1000000 , 985000 );
575+ IBCPacket memory packet = _createPacket ();
576+
577+ vm.prank (address (zkgm));
578+ vault.solve (packet, order, DEFAULT_PATH, address (0 ), RELAYER, "" , false );
579+
580+ uint256 debt = vault.fungibleCounterparty (
581+ DEFAULT_PATH, DEFAULT_CHANNEL_ID, BASE_TOKEN
582+ ).debt;
583+ assertEq (debt, 1000000 , "Initial debt should be 1000000 " );
584+
585+ quoteToken.mint (REPAYER, debt);
586+
587+ vm.startPrank (REPAYER);
588+ quoteToken.approve (address (vault), debt);
589+ vault.repay (DEFAULT_PATH, DEFAULT_CHANNEL_ID, BASE_TOKEN, debt);
590+ vm.stopPrank ();
591+
592+ assertEq (
593+ vault.fungibleCounterparty (
594+ DEFAULT_PATH, DEFAULT_CHANNEL_ID, BASE_TOKEN
595+ ).debt,
596+ 0 ,
597+ "Debt should be fully repaid "
598+ );
599+ assertEq (
600+ vault.deployedCapital (),
601+ 0 ,
602+ "Deployed capital should be zero after full repayment "
603+ );
604+ }
605+
606+ function testRepayExactDebtAmount () public {
607+ _setupCounterparty ();
608+ _fundVault (10000000 );
609+
610+ TokenOrderV2 memory order = _createTokenOrder (1000000 , 985000 );
611+ IBCPacket memory packet = _createPacket ();
612+
613+ vm.prank (address (zkgm));
614+ vault.solve (packet, order, DEFAULT_PATH, address (0 ), RELAYER, "" , false );
615+
616+ uint256 repayAmount = 1000000 ;
617+ quoteToken.mint (REPAYER, repayAmount);
618+
619+ uint256 vaultBalanceBefore = quoteToken.balanceOf (address (vault));
620+ uint256 repayerBalanceBefore = quoteToken.balanceOf (REPAYER);
621+
622+ vm.startPrank (REPAYER);
623+ quoteToken.approve (address (vault), repayAmount);
624+ vault.repay (DEFAULT_PATH, DEFAULT_CHANNEL_ID, BASE_TOKEN, repayAmount);
625+ vm.stopPrank ();
626+
627+ assertEq (
628+ quoteToken.balanceOf (address (vault)),
629+ vaultBalanceBefore + repayAmount,
630+ "Vault should receive exact repayment amount "
631+ );
632+ assertEq (
633+ quoteToken.balanceOf (REPAYER),
634+ repayerBalanceBefore - repayAmount,
635+ "Repayer should send exact repayment amount "
636+ );
637+ assertEq (
638+ vault.fungibleCounterparty (
639+ DEFAULT_PATH, DEFAULT_CHANNEL_ID, BASE_TOKEN
640+ ).debt,
641+ 0 ,
642+ "Debt should be zero "
643+ );
644+ }
645+
646+ function testRepayMultipleConsecutivePayments () public {
647+ _setupCounterparty ();
648+ _fundVault (10000000 );
649+
650+ TokenOrderV2 memory order = _createTokenOrder (1000000 , 985000 );
651+ IBCPacket memory packet = _createPacket ();
652+
653+ vm.prank (address (zkgm));
654+ vault.solve (packet, order, DEFAULT_PATH, address (0 ), RELAYER, "" , false );
655+
656+ uint256 totalDebt = 1000000 ;
657+ uint256 firstPayment = 300000 ;
658+ uint256 secondPayment = 400000 ;
659+ uint256 thirdPayment = 300000 ;
660+
661+ quoteToken.mint (REPAYER, totalDebt);
662+
663+ // First repayment
664+ vm.startPrank (REPAYER);
665+ quoteToken.approve (address (vault), firstPayment);
666+ vault.repay (DEFAULT_PATH, DEFAULT_CHANNEL_ID, BASE_TOKEN, firstPayment);
667+ assertEq (
668+ vault.fungibleCounterparty (
669+ DEFAULT_PATH, DEFAULT_CHANNEL_ID, BASE_TOKEN
670+ ).debt,
671+ 700000 ,
672+ "Debt after first payment "
673+ );
674+
675+ // Second repayment
676+ quoteToken.approve (address (vault), secondPayment);
677+ vault.repay (DEFAULT_PATH, DEFAULT_CHANNEL_ID, BASE_TOKEN, secondPayment);
678+ assertEq (
679+ vault.fungibleCounterparty (
680+ DEFAULT_PATH, DEFAULT_CHANNEL_ID, BASE_TOKEN
681+ ).debt,
682+ 300000 ,
683+ "Debt after second payment "
684+ );
685+
686+ // Third repayment
687+ quoteToken.approve (address (vault), thirdPayment);
688+ vault.repay (DEFAULT_PATH, DEFAULT_CHANNEL_ID, BASE_TOKEN, thirdPayment);
689+ assertEq (
690+ vault.fungibleCounterparty (
691+ DEFAULT_PATH, DEFAULT_CHANNEL_ID, BASE_TOKEN
692+ ).debt,
693+ 0 ,
694+ "Debt should be fully repaid after three payments "
695+ );
696+ vm.stopPrank ();
697+ }
698+
699+ function testRepayRevertInsufficientApproval () public {
700+ _setupCounterparty ();
701+ _fundVault (10000000 );
702+
703+ TokenOrderV2 memory order = _createTokenOrder (1000000 , 985000 );
704+ IBCPacket memory packet = _createPacket ();
705+
706+ vm.prank (address (zkgm));
707+ vault.solve (packet, order, DEFAULT_PATH, address (0 ), RELAYER, "" , false );
708+
709+ uint256 repayAmount = 500000 ;
710+ quoteToken.mint (REPAYER, repayAmount);
711+
712+ vm.startPrank (REPAYER);
713+ // Approve less than the repayment amount
714+ quoteToken.approve (address (vault), repayAmount - 1 );
715+ vm.expectRevert ();
716+ vault.repay (DEFAULT_PATH, DEFAULT_CHANNEL_ID, BASE_TOKEN, repayAmount);
717+ vm.stopPrank ();
718+ }
719+
720+ function testRepayRevertInsufficientBalance () public {
721+ _setupCounterparty ();
722+ _fundVault (10000000 );
723+
724+ TokenOrderV2 memory order = _createTokenOrder (1000000 , 985000 );
725+ IBCPacket memory packet = _createPacket ();
726+
727+ vm.prank (address (zkgm));
728+ vault.solve (packet, order, DEFAULT_PATH, address (0 ), RELAYER, "" , false );
729+
730+ uint256 repayAmount = 500000 ;
731+ // Only mint half of what's needed
732+ quoteToken.mint (REPAYER, repayAmount / 2 );
733+
734+ vm.startPrank (REPAYER);
735+ quoteToken.approve (address (vault), repayAmount);
736+ vm.expectRevert ();
737+ vault.repay (DEFAULT_PATH, DEFAULT_CHANNEL_ID, BASE_TOKEN, repayAmount);
738+ vm.stopPrank ();
739+ }
569740}
570741
571742contract CrosschainVaultERC4626Test is CrosschainVaultTestBase {
0 commit comments