Skip to content

Commit 4cbbb72

Browse files
chore(evm): comprehensive repay tests for vault
1 parent 2642782 commit 4cbbb72

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed

evm/tests/src/05-app/CrosschainVault.t.sol

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

571742
contract CrosschainVaultERC4626Test is CrosschainVaultTestBase {

0 commit comments

Comments
 (0)