From 4ee168bb47fd26958fa0b8dd9a7d87983e725601 Mon Sep 17 00:00:00 2001 From: Lucas Manuel Date: Thu, 3 Nov 2022 00:50:47 -0400 Subject: [PATCH] feat: Update to add `acceptLender` function (SC-9368) (#67) * feat: update to add acceptLender function * fix: rm unused vars and use expectRevert --- contracts/DebtLocker.sol | 23 +++++++++++++++++------ contracts/interfaces/IDebtLocker.sol | 5 +++++ contracts/interfaces/Interfaces.sol | 2 ++ tests/DebtLocker.t.sol | 19 ++++++++++++++++++- tests/accounts/LoanMigrator.sol | 8 ++++++++ tests/mocks/Mocks.sol | 8 ++++++++ 6 files changed, 58 insertions(+), 7 deletions(-) diff --git a/contracts/DebtLocker.sol b/contracts/DebtLocker.sol index 4d6ebf3..e383a3f 100644 --- a/contracts/DebtLocker.sol +++ b/contracts/DebtLocker.sol @@ -45,6 +45,23 @@ contract DebtLocker is IDebtLocker, DebtLockerStorage, MapleProxiedInternals { IMapleProxyFactory(_factory()).upgradeInstance(toVersion_, arguments_); } + /*************************************/ + /*** Liquidity Migration Functions ***/ + /*************************************/ + + function acceptLender() override external whenProtocolNotPaused { + require(msg.sender == _loanMigrator, "DL:AL:NOT_MIGRATOR"); + + IMapleLoanLike(_loan).acceptLender(); + } + + function setPendingLender(address newLender_) override external whenProtocolNotPaused { + require(msg.sender == _loanMigrator, "DL:SPL:NOT_MIGRATOR"); + + IMapleLoanLike(_loan).setPendingLender(newLender_); + } + + /*******************************/ /*** Pool Delegate Functions ***/ /*******************************/ @@ -110,12 +127,6 @@ contract DebtLocker is IDebtLocker, DebtLockerStorage, MapleProxiedInternals { emit FundsToCaptureSet(_fundsToCapture = amount_); } - function setPendingLender(address newLender_) override external whenProtocolNotPaused { - require(msg.sender == _loanMigrator, "DL:SPL:NOT_MIGRATOR"); - - IMapleLoanLike(_loan).setPendingLender(newLender_); - } - function setMinRatio(uint256 minRatio_) external override whenProtocolNotPaused { require(msg.sender == _getPoolDelegate(), "DL:SMR:NOT_PD"); diff --git a/contracts/interfaces/IDebtLocker.sol b/contracts/interfaces/IDebtLocker.sol index 3bf0ac0..575eb0f 100644 --- a/contracts/interfaces/IDebtLocker.sol +++ b/contracts/interfaces/IDebtLocker.sol @@ -43,6 +43,11 @@ interface IDebtLocker is IMapleProxied { /*** Functions ***/ /*****************/ + /** + * @dev Accepts the lender on a Maple Loan. + */ + function acceptLender() external; + /** * @dev Accept the new loan terms and trigger a refinance. * @param refinancer_ The address of the refinancer contract. diff --git a/contracts/interfaces/Interfaces.sol b/contracts/interfaces/Interfaces.sol index a0518fe..9558d95 100644 --- a/contracts/interfaces/Interfaces.sol +++ b/contracts/interfaces/Interfaces.sol @@ -36,6 +36,8 @@ interface IMapleGlobalsLike { interface IMapleLoanLike { + function acceptLender() external; + function acceptNewTerms(address refinancer_, uint256 deadline_, bytes[] calldata calls_, uint256 amount_) external; function claimableFunds() external view returns (uint256 claimableFunds_); diff --git a/tests/DebtLocker.t.sol b/tests/DebtLocker.t.sol index 8fdb753..bfd10e7 100644 --- a/tests/DebtLocker.t.sol +++ b/tests/DebtLocker.t.sol @@ -35,6 +35,8 @@ interface Hevm { // Sets block timestamp to `x`. function warp(uint256 x) external view; + function expectRevert(bytes calldata) external; + } contract DebtLockerTests is TestUtils { @@ -1114,7 +1116,6 @@ contract DebtLockerV4Migration is TestUtils { assertEq(debtLocker_.loanMigrator(), loanMigrator); } - function test_acl_setPendingLender() external { ( MapleLoan loan, DebtLocker debtLocker ) = _createFundAndDrawdownLoan(1_000_000, 30_000); @@ -1133,6 +1134,22 @@ contract DebtLockerV4Migration is TestUtils { assertEq(loan.pendingLender(), newLender); } + function test_acl_acceptLender() external { + ( , DebtLocker debtLocker ) = _createFundAndDrawdownLoan(1_000_000, 30_000); + + LoanMigrator loanMigrator = new LoanMigrator(); + LoanMigrator notLoanMigrator = new LoanMigrator(); + + poolDelegate.debtLocker_upgrade(address(debtLocker), 2, abi.encode(address(loanMigrator))); + + loanMigrator.debtLocker_setPendingLender(address(debtLocker), address(debtLocker)); // Set pending lender in Loan to get ACL to work + + vm.expectRevert("DL:AL:NOT_MIGRATOR"); + notLoanMigrator.debtLocker_acceptLender(address(debtLocker)); + + loanMigrator.try_debtLocker_acceptLender(address(debtLocker)); + } + function _createLoan(uint256 principalRequested_, uint256 collateralRequired_) internal returns (MapleLoan loan_) { address[2] memory assets = [address(collateralAsset), address(fundsAsset)]; uint256[3] memory termDetails = [uint256(10 days), uint256(30 days), 6]; diff --git a/tests/accounts/LoanMigrator.sol b/tests/accounts/LoanMigrator.sol index 2a6f267..9769d4a 100644 --- a/tests/accounts/LoanMigrator.sol +++ b/tests/accounts/LoanMigrator.sol @@ -5,10 +5,18 @@ import { IDebtLocker } from "../../contracts/interfaces/IDebtLocker.sol"; contract LoanMigrator { + function debtLocker_acceptLender(address debtLocker_) external { + IDebtLocker(debtLocker_).acceptLender(); + } + function debtLocker_setPendingLender(address debtLocker_, address newLender_) external { IDebtLocker(debtLocker_).setPendingLender(newLender_); } + function try_debtLocker_acceptLender(address debtLocker_) external returns (bool ok_) { + ( ok_, ) = debtLocker_.call(abi.encodeWithSelector(IDebtLocker.acceptLender.selector)); + } + function try_debtLocker_setPendingLender(address debtLocker_, address newLender_) external returns (bool ok_) { ( ok_, ) = debtLocker_.call(abi.encodeWithSelector(IDebtLocker.setPendingLender.selector, newLender_)); } diff --git a/tests/mocks/Mocks.sol b/tests/mocks/Mocks.sol index 39187b5..b729991 100644 --- a/tests/mocks/Mocks.sol +++ b/tests/mocks/Mocks.sol @@ -74,10 +74,18 @@ contract MockLoan { return 0; } + function acceptLender() external { + // Empty, just testing ACL + } + function acceptNewTerms(address refinancer_, bytes[] calldata calls_, uint256 amount_) external { // Empty, just testing ACL } + function setPendingLender(address lender_) external { + // Empty, just testing ACL + } + } contract MockGlobals {