diff --git a/contracts/DebtLocker.sol b/contracts/DebtLocker.sol index 7b13b2b..48635fa 100644 --- a/contracts/DebtLocker.sol +++ b/contracts/DebtLocker.sol @@ -49,7 +49,7 @@ contract DebtLocker is IDebtLocker, DebtLockerStorage, MapleProxiedInternals { /*** Pool Delegate Functions ***/ /*******************************/ - function acceptNewTerms(address refinancer_, bytes[] calldata calls_, uint256 amount_) external override whenProtocolNotPaused { + function acceptNewTerms(address refinancer_, uint256 deadline_, bytes[] calldata calls_, uint256 amount_) external override whenProtocolNotPaused { require(msg.sender == _getPoolDelegate(), "DL:ANT:NOT_PD"); address loanAddress = _loan; @@ -65,7 +65,7 @@ contract DebtLocker is IDebtLocker, DebtLockerStorage, MapleProxiedInternals { "DL:ANT:TRANSFER_FAILED" ); - IMapleLoanLike(loanAddress).acceptNewTerms(refinancer_, calls_, uint256(0)); + IMapleLoanLike(loanAddress).acceptNewTerms(refinancer_, deadline_, calls_, uint256(0)); // NOTE: This must be set after accepting the new terms, which affects the loan principal. _principalRemainingAtLastClaim = IMapleLoanLike(loanAddress).principal(); @@ -83,6 +83,12 @@ contract DebtLocker is IDebtLocker, DebtLockerStorage, MapleProxiedInternals { Liquidator(liquidator_).pullFunds(token_, destination_, amount_); } + function rejectNewTerms(address refinancer_, uint256 deadline_, bytes[] calldata calls_) external override { + require(msg.sender == _getPoolDelegate(), "DL:ANT:NOT_PD"); + + IMapleLoanLike(_loan).rejectNewTerms(refinancer_, deadline_, calls_); + } + function setAllowedSlippage(uint256 allowedSlippage_) external override whenProtocolNotPaused { require(msg.sender == _getPoolDelegate(), "DL:SAS:NOT_PD"); require(allowedSlippage_ <= uint256(10_000), "DL:SAS:INVALID_SLIPPAGE"); diff --git a/contracts/interfaces/IDebtLocker.sol b/contracts/interfaces/IDebtLocker.sol index 6e26d1c..88a0e74 100644 --- a/contracts/interfaces/IDebtLocker.sol +++ b/contracts/interfaces/IDebtLocker.sol @@ -46,10 +46,11 @@ interface IDebtLocker is IMapleProxied { /** * @dev Accept the new loan terms and trigger a refinance. * @param refinancer_ The address of the refinancer contract. + * @param deadline_ The deadline of the new terms proposal. * @param calls_ The array of encoded data that are to be executed as delegatecalls by the refinancer. * @param amount_ The amount of `fundsAsset` that is to be sent to the Loan as part of the transaction. */ - function acceptNewTerms(address refinancer_, bytes[] calldata calls_, uint256 amount_) external; + function acceptNewTerms(address refinancer_, uint256 deadline_, bytes[] calldata calls_, uint256 amount_) external; /** * @dev Claims funds to send to Pool. Handles funds from payments and liquidations. @@ -84,6 +85,14 @@ interface IDebtLocker is IMapleProxied { */ function triggerDefault() external; + /** + * @dev Reject the new loan terms. + * @param refinancer_ The address of the refinancer contract. + * @param deadline_ The deadline of the new terms proposal. + * @param calls_ The array of encoded data that are to be executed as delegatecalls by the refinancer. + */ + function rejectNewTerms(address refinancer_, uint256 deadline_, bytes[] calldata calls_) external; + /** * @dev Sets the allowed slippage for auctioneer (used to determine expected amount to be returned in flash loan). * @param allowedSlippage_ Basis points representation of allowed percent slippage from market price. diff --git a/contracts/interfaces/Interfaces.sol b/contracts/interfaces/Interfaces.sol index f3956af..ccebf11 100644 --- a/contracts/interfaces/Interfaces.sol +++ b/contracts/interfaces/Interfaces.sol @@ -36,10 +36,12 @@ interface IMapleGlobalsLike { interface IMapleLoanLike { - function acceptNewTerms(address refinancer_, bytes[] calldata calls_, uint256 amount_) external; + function acceptNewTerms(address refinancer_, uint256 deadline_, bytes[] calldata calls_, uint256 amount_) external; function claimableFunds() external view returns (uint256 claimableFunds_); + function claimFunds(uint256 amount_, address destination_) external; + function collateralAsset() external view returns (address collateralAsset_); function fundsAsset() external view returns (address fundsAsset_); @@ -50,10 +52,12 @@ interface IMapleLoanLike { function principalRequested() external view returns (uint256 principalRequested_); - function claimFunds(uint256 amount_, address destination_) external; - function repossess(address destination_) external returns (uint256 collateralAssetAmount_, uint256 fundsAssetAmount_); + function refinanceCommitment() external view returns (bytes32 refinanceCommitment_); + + function rejectNewTerms(address refinancer_, uint256 deadline_, bytes[] calldata calls_) external; + } interface IPoolLike { diff --git a/contracts/test/DebtLocker.t.sol b/contracts/test/DebtLocker.t.sol index b38ce90..107777e 100644 --- a/contracts/test/DebtLocker.t.sol +++ b/contracts/test/DebtLocker.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.7; import { TestUtils } from "../../modules/contract-test-utils/contracts/test.sol"; -import { MockERC20 } from "../../modules/erc20/src/test/mocks/MockERC20.sol"; +import { MockERC20 } from "../../modules/erc20/contracts/test/mocks/MockERC20.sol"; import { MapleLoan } from "../../modules/loan/contracts/MapleLoan.sol"; import { MapleLoanFactory } from "../../modules/loan/contracts/MapleLoanFactory.sol"; import { MapleLoanInitializer } from "../../modules/loan/contracts/MapleLoanInitializer.sol"; @@ -145,73 +145,83 @@ contract DebtLockerTests is TestUtils { /*************************/ /*** Make two payments ***/ /*************************/ + { + ( uint256 principal1, uint256 interest1, uint256 delegateFee, uint256 treasuryFee ) = loan.getNextPaymentBreakdown(); - ( uint256 principal1, uint256 interest1 ) = loan.getNextPaymentBreakdown(); + uint256 total1 = principal1 + interest1 + delegateFee + treasuryFee; - uint256 total1 = principal1 + interest1; + // Make a payment amount with interest and principal + fundsAsset.mint(address(this), total1); + fundsAsset.approve(address(loan), total1); // Mock payment amount - // Make a payment amount with interest and principal - fundsAsset.mint(address(this), total1); - fundsAsset.approve(address(loan), total1); // Mock payment amount + loan.makePayment(total1); - loan.makePayment(total1); + uint256 principal2; + uint256 interest2; - ( uint256 principal2, uint256 interest2 ) = loan.getNextPaymentBreakdown(); + ( principal2, interest2, delegateFee, treasuryFee ) = loan.getNextPaymentBreakdown(); - uint256 total2 = principal2 + interest2; + uint256 total2 = principal2 + interest2 + delegateFee + treasuryFee; - // Mock a second payment amount with interest and principal - fundsAsset.mint(address(this), total2); - fundsAsset.approve(address(loan), total2); // Mock payment amount + // Mock a second payment amount with interest and principal + fundsAsset.mint(address(this), total2); + fundsAsset.approve(address(loan), total2); // Mock payment amount - loan.makePayment(total2); + loan.makePayment(total2); - assertEq(fundsAsset.balanceOf(address(loan)), total1 + total2); - assertEq(fundsAsset.balanceOf(address(pool)), 0); + uint256 totalPayments = (total1 + total2) - (delegateFee + treasuryFee) * 2; - assertEq(debtLocker.principalRemainingAtLastClaim(), loan.principalRequested()); + assertEq(fundsAsset.balanceOf(address(loan)), totalPayments); + assertEq(fundsAsset.balanceOf(address(pool)), 0); - uint256[7] memory details = pool.claim(address(debtLocker)); + assertEq(debtLocker.principalRemainingAtLastClaim(), loan.principalRequested()); - assertEq(fundsAsset.balanceOf(address(loan)), 0); - assertEq(fundsAsset.balanceOf(address(pool)), total1 + total2); + uint256[7] memory details = pool.claim(address(debtLocker)); - assertEq(debtLocker.principalRemainingAtLastClaim(), loan.principal()); + assertEq(fundsAsset.balanceOf(address(loan)), 0); + assertEq(fundsAsset.balanceOf(address(pool)), totalPayments); - assertEq(details[0], total1 + total2); // Total amount of funds claimed - assertEq(details[1], interest1 + interest2); // Excess funds go towards interest - assertEq(details[2], principal1 + principal2); // Principal amount - assertEq(details[3], 0); // `feePaid` is always zero since PD establishment fees are paid in `fundLoan` now - assertEq(details[4], 0); // `excessReturned` is always zero since new loans cannot be over-funded - assertEq(details[5], 0); // Total recovered from liquidation is zero - assertEq(details[6], 0); // Zero shortfall since no liquidation + assertEq(debtLocker.principalRemainingAtLastClaim(), loan.principal()); + + assertEq(details[0], totalPayments); // Total amount of funds claimed + assertEq(details[1], interest1 + interest2); // Excess funds go towards interest + assertEq(details[2], principal1 + principal2); // Principal amount + assertEq(details[3], 0); // `feePaid` is always zero since PD establishment fees are paid in `fundLoan` now + assertEq(details[4], 0); // `excessReturned` is always zero since new loans cannot be over-funded + assertEq(details[5], 0); // Total recovered from liquidation is zero + assertEq(details[6], 0); // Zero shortfall since no liquidation + } /*************************/ /*** Make last payment ***/ /*************************/ - ( uint256 principal3, uint256 interest3 ) = loan.getNextPaymentBreakdown(); + { + ( uint256 principal3, uint256 interest3, uint256 delegateFee, uint256 treasuryFee ) = loan.getNextPaymentBreakdown(); - uint256 total3 = principal3 + interest3; + uint256 total3 = principal3 + interest3 + delegateFee + treasuryFee; - // Make a payment amount with interest and principal - fundsAsset.mint(address(this), total3); - fundsAsset.approve(address(loan), total3); // Mock payment amount + // Make a payment amount with interest and principal + fundsAsset.mint(address(this), total3); + fundsAsset.approve(address(loan), total3); // Mock payment amount + + // Reduce the principal in loan and set claimableFunds + loan.makePayment(total3); - // Reduce the principal in loan and set claimableFunds - loan.makePayment(total3); + uint256 poolBal = fundsAsset.balanceOf(address(pool)); - details = pool.claim(address(debtLocker)); + uint256[7] memory details = pool.claim(address(debtLocker)); - assertEq(fundsAsset.balanceOf(address(pool)), total1 + total2 + total3); + assertEq(fundsAsset.balanceOf(address(pool)), poolBal + interest3 + principal3); - assertEq(details[0], total3); // Total amount of funds claimed - assertEq(details[1], interest3); // Excess funds go towards interest - assertEq(details[2], principal3); // Principal amount - assertEq(details[3], 0); // `feePaid` is always zero since PD establishment fees are paid in `fundLoan` now - assertEq(details[4], 0); // `excessReturned` is always zero since new loans cannot be over-funded - assertEq(details[5], 0); // Total recovered from liquidation is zero - assertEq(details[6], 0); // Zero shortfall since no liquidation + assertEq(details[0], total3 - delegateFee - treasuryFee); // Total amount of funds claimed + assertEq(details[1], interest3); // Excess funds go towards interest + assertEq(details[2], principal3); // Principal amount + assertEq(details[3], 0); // `feePaid` is always zero since PD establishment fees are paid in `fundLoan` now + assertEq(details[4], 0); // `excessReturned` is always zero since new loans cannot be over-funded + assertEq(details[5], 0); // Total recovered from liquidation is zero + assertEq(details[6], 0); // Zero shortfall since no liquidation + } } function test_initialize_invalidCollateralAsset() external { @@ -261,9 +271,10 @@ contract DebtLockerTests is TestUtils { /*** Make a payment ***/ /**********************/ - ( uint256 principal, uint256 interest ) = loan.getNextPaymentBreakdown(); + ( uint256 principal, uint256 interest, uint256 delegateFee, uint256 treasuryFee ) = loan.getNextPaymentBreakdown(); - uint256 total = principal + interest; + uint256 total = principal + interest + delegateFee + treasuryFee; + uint256 totalPayment = principal + interest; // Make a payment amount with interest and principal fundsAsset.mint(address(this), total); @@ -277,7 +288,7 @@ contract DebtLockerTests is TestUtils { assertEq(collateralAsset.balanceOf(address(loan)), collateralRequired_); assertEq(collateralAsset.balanceOf(address(debtLocker)), 0); - assertEq(fundsAsset.balanceOf(address(loan)), total); + assertEq(fundsAsset.balanceOf(address(loan)), totalPayment); assertEq(fundsAsset.balanceOf(address(debtLocker)), 0); assertEq(fundsAsset.balanceOf(address(pool)), 0); assertTrue(!debtLocker.repossessed()); @@ -300,7 +311,7 @@ contract DebtLockerTests is TestUtils { assertEq(fundsAsset.balanceOf(address(loan)), 0); assertEq(fundsAsset.balanceOf(address(debtLocker)), 0); assertEq(fundsAsset.balanceOf(liquidator), 0); - assertEq(fundsAsset.balanceOf(address(pool)), total); + assertEq(fundsAsset.balanceOf(address(pool)), totalPayment); assertTrue(debtLocker.repossessed()); if (collateralRequired_ > 0) { @@ -321,12 +332,12 @@ contract DebtLockerTests is TestUtils { assertEq(fundsAsset.balanceOf(address(loan)), 0); assertEq(fundsAsset.balanceOf(address(debtLocker)), amountRecovered); assertEq(fundsAsset.balanceOf(liquidator), 0); - assertEq(fundsAsset.balanceOf(address(pool)), total); + assertEq(fundsAsset.balanceOf(address(pool)), totalPayment); uint256[7] memory details = pool.claim(address(debtLocker)); assertEq(fundsAsset.balanceOf(address(debtLocker)), 0); - assertEq(fundsAsset.balanceOf(address(pool)), total + amountRecovered); + assertEq(fundsAsset.balanceOf(address(pool)), totalPayment + amountRecovered); assertTrue(!debtLocker.repossessed()); assertEq(details[0], amountRecovered); // Total amount of funds claimed @@ -703,16 +714,37 @@ contract DebtLockerTests is TestUtils { bytes[] memory data = new bytes[](1); data[0] = abi.encodeWithSignature("setEarlyFeeRate(uint256)", 100); - loan.proposeNewTerms(refinancer, data); // address(this) is borrower + uint256 deadline = block.timestamp + 1; + + loan.proposeNewTerms(refinancer, deadline, data); // address(this) is borrower assertEq(loan.earlyFeeRate(), 0); - assertTrue(!notPoolDelegate.try_debtLocker_acceptNewTerms(address(debtLocker), refinancer, data, 0)); // Non-PD can't set - assertTrue( poolDelegate.try_debtLocker_acceptNewTerms(address(debtLocker), refinancer, data, 0)); // PD can set + assertTrue(!notPoolDelegate.try_debtLocker_acceptNewTerms(address(debtLocker), refinancer, deadline, data, 0)); // Non-PD can't set + assertTrue( poolDelegate.try_debtLocker_acceptNewTerms(address(debtLocker), refinancer, deadline, data, 0)); // PD can set assertEq(loan.earlyFeeRate(), 100); } + function test_acl_poolDelegate_rejectNewTerms() external { + ( MapleLoan loan, DebtLocker debtLocker ) = _createFundAndDrawdownLoan(1_000_000, 30_000); + + address refinancer = address(new Refinancer()); + bytes[] memory data = new bytes[](1); + data[0] = abi.encodeWithSignature("setEarlyFeeRate(uint256)", 100); + + uint256 deadline = block.timestamp + 1; + + loan.proposeNewTerms(refinancer, deadline, data); // address(this) is borrower + + assertTrue(loan.refinanceCommitment() != bytes32(0)); + + assertTrue(!notPoolDelegate.try_debtLocker_rejectNewTerms(address(debtLocker), refinancer, deadline, data)); // Non-PD can't set + assertTrue( poolDelegate.try_debtLocker_rejectNewTerms(address(debtLocker), refinancer, deadline, data)); // PD can set + + assertTrue(loan.refinanceCommitment() == bytes32(0)); + } + function test_acl_pool_claim() external { MapleLoan loan = _createLoan(1_000_000, 30_000); @@ -720,9 +752,9 @@ contract DebtLockerTests is TestUtils { _fundAndDrawdownLoan(address(loan), address(debtLocker)); - ( uint256 principal1, uint256 interest1 ) = loan.getNextPaymentBreakdown(); + ( uint256 principal1, uint256 interest1, uint256 delegateFee1, uint256 treasuryFee1 ) = loan.getNextPaymentBreakdown(); - uint256 total1 = principal1 + interest1; + uint256 total1 = principal1 + interest1 + delegateFee1 + treasuryFee1; // Make a payment amount with interest and principal fundsAsset.mint(address(this), total1); @@ -774,55 +806,55 @@ contract DebtLockerTests is TestUtils { /*** Refinance Tests ***/ /***********************/ - function test_refinance_withAmountIncrease(uint256 principalRequested_, uint256 collateralRequired_, uint256 principalIncrease_) external { - principalRequested_ = constrictToRange(principalRequested_, 1_000_000, MAX_TOKEN_AMOUNT); - collateralRequired_ = constrictToRange(collateralRequired_, 0, principalRequested_ / 10); - principalIncrease_ = constrictToRange(principalIncrease_, 1, MAX_TOKEN_AMOUNT); + function test_acceptNewTerms_withAmountIncrease(uint256 principalIncrease_) external { + principalIncrease_ = constrictToRange(principalIncrease_, 1, 1_000_000); /**********************************/ /*** Create Loan and DebtLocker ***/ /**********************************/ - ( MapleLoan loan, DebtLocker debtLocker ) = _createFundAndDrawdownLoan(principalRequested_, collateralRequired_); + ( MapleLoan loan, DebtLocker debtLocker ) = _createFundAndDrawdownLoan(1_000_000, 100_000); /**********************/ /*** Make a payment ***/ /**********************/ - ( uint256 principal, uint256 interest ) = loan.getNextPaymentBreakdown(); + ( uint256 principal, uint256 interest, uint256 delegateFee, uint256 treasuryFee ) = loan.getNextPaymentBreakdown(); - uint256 total = principal + interest; + { + uint256 total = principal + interest + delegateFee + treasuryFee; - // Make a payment amount with interest and principal - fundsAsset.mint(address(this), total); - fundsAsset.approve(address(loan), total); // Mock payment amount + // Make a payment amount with interest and principal + fundsAsset.mint(address(this), total); + fundsAsset.approve(address(loan), total); // Mock payment amount - loan.makePayment(total); + loan.makePayment(total); + } - /******************/ + /*****************/ /*** Refinance ***/ - /****************/ + /*****************/ address refinancer = address(new Refinancer()); bytes[] memory data = new bytes[](1); data[0] = abi.encodeWithSignature("increasePrincipal(uint256)", principalIncrease_); - loan.proposeNewTerms(refinancer, data); + loan.proposeNewTerms(refinancer, block.timestamp, data); fundsAsset.mint(address(debtLocker), principalIncrease_); // Should fail due to pending claim - try debtLocker.acceptNewTerms(refinancer, data, principalIncrease_) { fail(); } catch { } + try debtLocker.acceptNewTerms(refinancer, block.timestamp, data, principalIncrease_) { fail(); } catch { } pool.claim(address(debtLocker)); // Should fail for not pool delegate - try notPoolDelegate.debtLocker_acceptNewTerms(address(debtLocker), refinancer, data, principalIncrease_) { fail(); } catch { } + try notPoolDelegate.debtLocker_acceptNewTerms(address(debtLocker), refinancer, block.timestamp, data, principalIncrease_) { fail(); } catch { } // Note: More state changes in real loan that are asserted in integration tests uint256 principalBefore = loan.principal(); - poolDelegate.debtLocker_acceptNewTerms(address(debtLocker), refinancer, data, principalIncrease_); + poolDelegate.debtLocker_acceptNewTerms(address(debtLocker), refinancer, block.timestamp, data, principalIncrease_); uint256 principalAfter = loan.principal(); @@ -840,8 +872,9 @@ contract DebtLockerTests is TestUtils { ( MapleLoan loan, DebtLocker debtLocker ) = _createFundAndDrawdownLoan(1_000_000, 30_000); // Make a payment amount with interest and principal - ( uint256 principal, uint256 interest ) = loan.getNextPaymentBreakdown(); - fundsAsset.mint(address(loan), principal + interest); + ( uint256 principal, uint256 interest, uint256 delegateFee, uint256 treasuryFee ) = loan.getNextPaymentBreakdown(); + + fundsAsset.mint(address(loan), principal + interest + delegateFee + treasuryFee); loan.makePayment(0); // Prepare additional amount to be captured in next claim @@ -917,8 +950,9 @@ contract DebtLockerTests is TestUtils { loan.fundLoan(address(debtLocker), 1_000_000); // Make a payment amount with interest and principal - ( uint256 principal, uint256 interest ) = loan.getNextPaymentBreakdown(); - fundsAsset.mint(address(loan), principal + interest); + ( uint256 principal, uint256 interest, uint256 delegateFee, uint256 treasuryFee ) = loan.getNextPaymentBreakdown(); + + fundsAsset.mint(address(loan), principal + interest + delegateFee + treasuryFee); loan.makePayment(principal + interest); // Erroneously prepare additional amount to be captured in next claim diff --git a/contracts/test/accounts/PoolDelegate.sol b/contracts/test/accounts/PoolDelegate.sol index 925f41f..7a681f7 100644 --- a/contracts/test/accounts/PoolDelegate.sol +++ b/contracts/test/accounts/PoolDelegate.sol @@ -11,14 +11,18 @@ contract PoolDelegate is ProxyUser { /*** Direct Functions ***/ /************************/ - function debtLocker_acceptNewTerms(address debtLocker_, address refinancer_, bytes[] calldata calls_, uint256 amount_) external { - IDebtLocker(debtLocker_).acceptNewTerms(refinancer_, calls_, amount_); + function debtLocker_acceptNewTerms(address debtLocker_, address refinancer_, uint256 deadline_, bytes[] calldata calls_, uint256 amount_) external { + IDebtLocker(debtLocker_).acceptNewTerms(refinancer_, deadline_, calls_, amount_); } function debtLocker_pullFunds(address debtLocker_, address liquidator_, address token_, address destination_, uint256 amount_) external { IDebtLocker(debtLocker_).pullFundsFromLiquidator(liquidator_, token_, destination_, amount_); } + function debtLocker_rejectNewTerms(address debtLocker_, address refinancer_, uint256 deadline_, bytes[] calldata calls_) external { + IDebtLocker(debtLocker_).rejectNewTerms(refinancer_, deadline_, calls_); + } + function debtLocker_setAllowedSlippage(address debtLocker_, uint256 allowedSlippage_) external { IDebtLocker(debtLocker_).setAllowedSlippage(allowedSlippage_); } @@ -50,15 +54,25 @@ contract PoolDelegate is ProxyUser { function try_debtLocker_acceptNewTerms( address debtLocker_, address refinancer_, + uint256 deadline_, bytes[] calldata calls_, uint256 amount_ ) external returns (bool ok_) { - ( ok_, ) = debtLocker_.call(abi.encodeWithSelector(IDebtLocker.acceptNewTerms.selector, refinancer_, calls_, amount_)); + ( ok_, ) = debtLocker_.call(abi.encodeWithSelector(IDebtLocker.acceptNewTerms.selector, refinancer_, deadline_, calls_, amount_)); } function try_debtLocker_pullFunds(address debtLocker_, address liquidator_, address token_, address destination_, uint256 amount_) external returns (bool ok_) { ( ok_, ) = debtLocker_.call(abi.encodeWithSelector(IDebtLocker.pullFundsFromLiquidator.selector, liquidator_, token_, destination_, amount_)); -} + } + + function try_debtLocker_rejectNewTerms( + address debtLocker_, + address refinancer_, + uint256 deadline_, + bytes[] calldata calls_ + ) external returns (bool ok_) { + ( ok_, ) = debtLocker_.call(abi.encodeWithSelector(IDebtLocker.rejectNewTerms.selector, refinancer_, deadline_, calls_)); + } function try_debtLocker_setAllowedSlippage(address debtLocker_, uint256 allowedSlippage_) external returns (bool ok_) { ( ok_, ) = debtLocker_.call(abi.encodeWithSelector(IDebtLocker.setAllowedSlippage.selector, allowedSlippage_)); diff --git a/contracts/test/mocks/Mocks.sol b/contracts/test/mocks/Mocks.sol index d1938b1..bed20f5 100644 --- a/contracts/test/mocks/Mocks.sol +++ b/contracts/test/mocks/Mocks.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.7; import { ILiquidatorLike } from "../../../modules/liquidations/contracts/interfaces/Interfaces.sol"; import { ERC20Helper } from "../../../modules/erc20-helper/src/ERC20Helper.sol"; -import { MockERC20 } from "../../../modules/erc20/src/test/mocks/MockERC20.sol"; +import { MockERC20 } from "../../../modules/erc20/contracts/test/mocks/MockERC20.sol"; import { IDebtLocker } from "../../interfaces/IDebtLocker.sol"; import { IDebtLockerFactory } from "../../interfaces/IDebtLockerFactory.sol"; diff --git a/modules/erc20 b/modules/erc20 index c3d599d..756c110 160000 --- a/modules/erc20 +++ b/modules/erc20 @@ -1 +1 @@ -Subproject commit c3d599d9976144f0c20d25a14126741fdd2edea2 +Subproject commit 756c110ddc3c96c596a52bce43553477a19ee3aa diff --git a/modules/erc20-helper b/modules/erc20-helper index 5961b58..d674c62 160000 --- a/modules/erc20-helper +++ b/modules/erc20-helper @@ -1 +1 @@ -Subproject commit 5961b58b75004356da04ec2b5b70eff40a1827f3 +Subproject commit d674c62600d43b7472d15067b282d42361aa7d02 diff --git a/modules/loan b/modules/loan index 21a6d7d..58cbe52 160000 --- a/modules/loan +++ b/modules/loan @@ -1 +1 @@ -Subproject commit 21a6d7d76e58b575aac21eb1cb8d1e7659b77758 +Subproject commit 58cbe527d4bfec57d9981f9d839898de7883dc65