diff --git a/contracts/DebtLocker.sol b/contracts/DebtLocker.sol index 297c653..13fb99c 100644 --- a/contracts/DebtLocker.sol +++ b/contracts/DebtLocker.sol @@ -78,10 +78,10 @@ contract DebtLocker is IDebtLocker, DebtLockerStorage, MapleProxied { return _repossessed ? _handleClaimOfRepossessed(msg.sender, _loan) : _handleClaim(msg.sender, _loan); } - function pullFundsFromLiquidator(address token_, address destination_, uint256 amount_) external override { + function pullFundsFromLiquidator(address liquidator_, address token_, address destination_, uint256 amount_) external override { require(msg.sender == _getPoolDelegate(), "DL:SA:NOT_PD"); - Liquidator(_liquidator).pullFunds(token_, destination_, amount_); + Liquidator(liquidator_).pullFunds(token_, destination_, amount_); } function setAllowedSlippage(uint256 allowedSlippage_) external override whenProtocolNotPaused { diff --git a/contracts/interfaces/IDebtLocker.sol b/contracts/interfaces/IDebtLocker.sol index f41d745..892de78 100644 --- a/contracts/interfaces/IDebtLocker.sol +++ b/contracts/interfaces/IDebtLocker.sol @@ -64,11 +64,12 @@ interface IDebtLocker is IMapleProxied { /** * @dev Allows the poolDelegate to pull some funds from liquidator contract + * @param liquidator_ The liquidator to which pull funds from. * @param token_ The token address of the funds. * @param destination_ The destination address of captured funds. * @param amount_ The amount to pull. */ - function pullFundsFromLiquidator(address token_, address destination_, uint256 amount_) external; + function pullFundsFromLiquidator(address liquidator_, address token_, address destination_, uint256 amount_) external; /** * @dev Returns the address of the Pool Delegate that has control of the DebtLocker. diff --git a/contracts/test/DebtLocker.t.sol b/contracts/test/DebtLocker.t.sol index e7ad509..1798d98 100644 --- a/contracts/test/DebtLocker.t.sol +++ b/contracts/test/DebtLocker.t.sol @@ -545,6 +545,37 @@ contract DebtLockerTests is TestUtils { pool.claim(address(debtLocker)); // Can successfully claim } + function test_liquidation_pullFunds(uint256 principalRequested_, uint256 collateralRequired_) external { + + /**********************************/ + /*** Create Loan and DebtLocker ***/ + /**********************************/ + + principalRequested_ = constrictToRange(principalRequested_, 1_000_000, MAX_TOKEN_AMOUNT); + collateralRequired_ = constrictToRange(collateralRequired_, 1, principalRequested_ / 10); // Need collateral for liquidator deployment + + ( MapleLoan loan, DebtLocker debtLocker ) = _createFundAndDrawdownLoan(principalRequested_, collateralRequired_); + + /*************************************/ + /*** Trigger default and liquidate ***/ + /*************************************/ + + hevm.warp(loan.nextPaymentDueDate() + loan.gracePeriod() + 1); + + pool.triggerDefault(address(debtLocker)); + + address liquidator = debtLocker.liquidator(); + + assertEq(collateralAsset.balanceOf(address(this)), 0); + assertEq(collateralAsset.balanceOf(address(liquidator)), collateralRequired_); + + assertTrue(!notPoolDelegate.try_debtLocker_pullFunds(address(debtLocker), address(liquidator), address(collateralAsset), address(this), collateralRequired_)); + assertTrue( poolDelegate.try_debtLocker_pullFunds(address(debtLocker), address(liquidator), address(collateralAsset), address(this), collateralRequired_)); + + assertEq(collateralAsset.balanceOf(address(this)), collateralRequired_); + assertEq(collateralAsset.balanceOf(address(liquidator)), 0); + } + /****************************/ /*** Access Control Tests ***/ /****************************/ diff --git a/contracts/test/accounts/PoolDelegate.sol b/contracts/test/accounts/PoolDelegate.sol index b2ee578..4a6d648 100644 --- a/contracts/test/accounts/PoolDelegate.sol +++ b/contracts/test/accounts/PoolDelegate.sol @@ -15,6 +15,10 @@ contract PoolDelegate is ProxyUser { IDebtLocker(debtLocker_).acceptNewTerms(refinancer_, 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_setAllowedSlippage(address debtLocker_, uint256 allowedSlippage_) external { IDebtLocker(debtLocker_).setAllowedSlippage(allowedSlippage_); } @@ -52,6 +56,10 @@ contract PoolDelegate is ProxyUser { ( ok_, ) = debtLocker_.call(abi.encodeWithSelector(IDebtLocker.acceptNewTerms.selector, refinancer_, 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_setAllowedSlippage(address debtLocker_, uint256 allowedSlippage_) external returns (bool ok_) { ( ok_, ) = debtLocker_.call(abi.encodeWithSelector(IDebtLocker.setAllowedSlippage.selector, allowedSlippage_)); }