Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Line of credit status can be set to REPAID even if having credits with debt #334

Closed
code423n4 opened this issue Nov 10, 2022 · 2 comments
Closed
Labels
3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working duplicate-258 satisfactory Finding meets requirement

Comments

@code423n4
Copy link
Contributor

Lines of code

https://github.com/debtdao/Line-of-Credit/blob/audit/code4rena-2022-11-03/contracts/modules/credit/LineOfCredit.sol#L388
https://github.com/debtdao/Line-of-Credit/blob/audit/code4rena-2022-11-03/contracts/modules/credit/LineOfCredit.sol#L502

Vulnerability details

A malicious borrower can close non-existing credits to alter the status of the credit to LineLib.STATUS.REPAID, even if having open credit with debt.

Impact

The _close function in the LineOfCredit contract can be used to close non-existing credits, which will decrease the credit count variable, and may be exploitable by a malicious borrower to move the line of credit to a REPAID status and regain control of the Spigot while still having open credits with debt.

Since the _close function doesn't validate credits, it can be called with non-existing/invalid credit ids to artificially decrease the credit count variable, which is used to track open credits, and will move the line status to REPAID if it gets to 0. Once the count is 0, the attacker can simply call the SpigotedLibe.releaseSpigot function to regain control of the Spigot. This will allow him to control back the source of revenue while not paying any debt.

PoC

In this test, the borrower borrows funds from a credit, then proceeds to close an non-existing credit, which will move the credit count from 1 to 0. This will update the line status to LineLib.STATUS.REPAID.

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_UpdateStatusToRepaidWhileDebt() public {
    address lender = makeAddr("lender");
    _mintAndApprove(lender);
    
    uint256 amount = 1 ether;
    
    _addCredit(lender, address(supportedToken1), amount);
    bytes32 id = CreditLib.computeId(address(line), lender, address(supportedToken1));
    
    vm.prank(borrower);
    line.borrow(id, amount);
    
    // Line is active and borrower has an open credit with debt
    assertEq(uint256(line.status()), uint256(LineLib.STATUS.ACTIVE));
    
    vm.prank(borrower);
    line.close(keccak256("UnexistentCredit"));
    
    // By closing another non-existent credit we can update the status to REPAID while still having open debt
    assertEq(uint256(line.status()), uint256(LineLib.STATUS.REPAID));
}

Recommendation

Verify credits are valid and haven't been already closed when closing credit in the _close function of the LineOfCredit contract.

@code423n4 code423n4 added 3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working labels Nov 10, 2022
code423n4 added a commit that referenced this issue Nov 10, 2022
@c4-judge
Copy link
Contributor

dmvt marked the issue as duplicate of #258

@c4-judge
Copy link
Contributor

c4-judge commented Dec 6, 2022

dmvt marked the issue as satisfactory

@c4-judge c4-judge added the satisfactory Finding meets requirement label Dec 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working duplicate-258 satisfactory Finding meets requirement
Projects
None yet
Development

No branches or pull requests

2 participants