diff --git a/contracts/DebtLocker.sol b/contracts/DebtLocker.sol index a47fec2..1da2dd6 100644 --- a/contracts/DebtLocker.sol +++ b/contracts/DebtLocker.sol @@ -53,6 +53,8 @@ contract DebtLocker is IDebtLocker, DebtLockerStorage, MapleProxied { require(amount_ == uint256(0) || ERC20Helper.transfer(loan_.fundsAsset(), address(_loan), amount_)); loan_.acceptNewTerms(refinancer_, calls_, uint256(0)); + + _principalRemainingAtLastClaim = loan_.principal(); } function setFundsToCapture(uint256 amount_) override external { @@ -209,19 +211,24 @@ contract DebtLocker is IDebtLocker, DebtLockerStorage, MapleProxied { require(!_isLiquidationActive(), "DL:HCOR:LIQ_NOT_FINISHED"); address fundsAsset = IMapleLoanLike(_loan).fundsAsset(); - uint256 recoveredFunds = IERC20Like(fundsAsset).balanceOf(address(this)); // Funds recovered from liquidation and any unclaimed previous payment amounts - uint256 principalToCover = _principalRemainingAtLastClaim; // Principal remaining at time of liquidation + uint256 principalToCover = _principalRemainingAtLastClaim; // Principal remaining at time of liquidation + uint256 fundsCaptured = _fundsToCapture; + + // Funds recovered from liquidation and any unclaimed previous payment amounts + uint256 recoveredFunds = IERC20Like(fundsAsset).balanceOf(address(this)) - fundsCaptured; // If `recoveredFunds` is greater than `principalToCover`, the remaining amount is treated as interest in the context of the pool. // If `recoveredFunds` is less than `principalToCover`, the difference is registered as a shortfall. - details_[0] = recoveredFunds; + details_[0] = recoveredFunds + fundsCaptured; details_[1] = recoveredFunds > principalToCover ? recoveredFunds - principalToCover : 0; + details_[2] = fundsCaptured; details_[5] = recoveredFunds > principalToCover ? principalToCover : recoveredFunds; details_[6] = principalToCover > recoveredFunds ? principalToCover - recoveredFunds : 0; - require(ERC20Helper.transfer(fundsAsset, _pool, recoveredFunds), "DL:HCOR:TRANSFER"); + require(ERC20Helper.transfer(fundsAsset, _pool, recoveredFunds + fundsCaptured), "DL:HCOR:TRANSFER"); - _repossessed = false; + _fundsToCapture = uint256(0); + _repossessed = false; } function _handleClaim() internal returns (uint256[7] memory details_) { diff --git a/contracts/test/DebtLocker.t.sol b/contracts/test/DebtLocker.t.sol index 3a20cf3..f106187 100644 --- a/contracts/test/DebtLocker.t.sol +++ b/contracts/test/DebtLocker.t.sol @@ -532,7 +532,8 @@ contract DebtLockerTest is TestUtils { uint256 principalAfter = loan.principal(); - assertEq(principalBefore + principalIncrease_, principalAfter); + assertEq(principalBefore + principalIncrease_, principalAfter); + assertEq(debtLocker.principalRemainingAtLastClaim(), principalAfter); } function test_fundsToCaptureForNextClaim() public { @@ -590,4 +591,39 @@ contract DebtLockerTest is TestUtils { pool.claim(address(debtLocker)); } + function test_fundsToCaptureWhileInDefault() public { + ( loan, debtLocker ) = _createFundAndDrawdownLoan(1_000_000); + + // Prepare additional amount to be captured + fundsAsset.mint(address(debtLocker), 500_000); + + assertEq(fundsAsset.balanceOf(address(debtLocker)), 500_000); + assertEq(fundsAsset.balanceOf(address(pool)), 0); + assertEq(debtLocker.principalRemainingAtLastClaim(), loan.principalRequested()); + assertEq(debtLocker.fundsToCapture(), 0); + + // Trigger default + hevm.warp(loan.nextPaymentDueDate() + loan.gracePeriod() + 1); + + pool.triggerDefault(address(debtLocker)); + + // After triggering default, set funds to capture + poolDelegate.debtLocker_setFundsToCapture(address(debtLocker), 500_000); + + // Claim + uint256[7] memory details = pool.claim(address(debtLocker)); + + assertEq(fundsAsset.balanceOf(address(debtLocker)), 0); + assertEq(fundsAsset.balanceOf(address(pool)), 500_000); + assertEq(debtLocker.fundsToCapture(), 0); + + assertEq(details[0], 500_000); + assertEq(details[1], 0); + assertEq(details[2], 500_000); + assertEq(details[3], 0); + assertEq(details[4], 0); + assertEq(details[5], 0); + assertEq(details[6], loan.principalRequested()); // No principal was recovered + } + }