Skip to content

Latest commit

 

History

History
47 lines (30 loc) · 2.44 KB

M-06.md

File metadata and controls

47 lines (30 loc) · 2.44 KB

close function in LineOfCredit can't be called by the lender if credit is in ETH

The close function allows a lender or borrower to finalize a credit (whose principal has been already paid) by repaying all of the accrued interest generated by facility rates. This function won't work as intended if the lender is the caller and the credit was given in ETH, because ETH can't be pulled from the borrower.

Impact

When a lender closes a credit using the close function in the LineOfCredit contract, the LineLib.receiveTokenOrETH function will be used to pull payments from the borrower.

In case the credit is using an ERC20 token as the credit payment, this will work fine as long as the borrower has enough balance and has previously approved the line contract to transfer funds. The lender will be able to call the close function, which will pull all of the interest accrued from the borrower's balance to repay all debt and finalize the credit.

But in the case the credit was created using native ETH this won't work. If the lender wants to close the credit, and assuming the borrower has enough balance to pay for it, LineLib.receiveTokenOrETH won't be able to pull ETH payments from the borrower.

PoC

The following test creates a credit using ETH and moves forward in time to simulate some debt from facility rates. The close function call will fail when the lender wants to finalize his credit.

Note: the context for this test (setup, variables and helper functions) is similar to the one found in the file LineOfCredit.t.sol.

function test_close_CantPullETHFromBorrower() public {
    address lender = makeAddr("lender");
    _mintAndApprove(lender);

    uint256 amount = 1 ether;

    // Setup credit (borrower goes first to avoid error on create)
    vm.prank(borrower);
    line.addCredit(dRate, fRate, amount, Denominations.ETH, lender);

    vm.prank(lender);
    bytes32 id = line.addCredit{value: amount}(dRate, fRate, amount, Denominations.ETH, lender);

    vm.warp(block.timestamp + 30 days);
    
    // Make sure borrower has balance to pay any debt
    vm.deal(borrower, 1 ether);

    // LineLib.receiveTokenOrETH will pull ERC20 from borrower but can't pull ETH
    vm.expectRevert(LineLib.TransferFailed.selector);
    vm.prank(lender);
    line.close(id);
}

Recommendation

Instead of using native ETH (or the equivalent in the chain this gets deployed) use the wrapped ERC20 version WETH. This will enable pull payments for ETH.