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

Lost funds over a misplaced value #182

Closed
code423n4 opened this issue Nov 9, 2022 · 3 comments
Closed

Lost funds over a misplaced value #182

code423n4 opened this issue Nov 9, 2022 · 3 comments
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working duplicate-39 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/utils/LineLib.sol#L59-L74

Vulnerability details

Impact

In DebtDao, a credit line can be created over any whitelisted erc20 token or ETH. A mutual agreement, between the borrower and the lender, establishes the parameters with which a line is created. Whenever the agreement is over a token, the balance and amounts (owed and due) are managed in accordance with the token's implementation. But if the agreement is over ETH, there's a potential mismatch between balances and the amounts registered using the Denominations.ETH placeholder.

Thus, in receiveTokenOrETH, since the concern is to protect the line in amounts received less than expected (if(msg.value < amount) { revert TransferFailed(); }), it allows for potential mistakes whenever an end-user calls addCredit, increaseCredit, depositAndClose, depositAndRepay and close.

External requirements:

  • lender or borrower transfers a value greater than the intended amount.

Proof of Concept

Simple scenario where the lender transfers a bigger value than the amount agreed with the borrower. After the borrower pays his dues, the line keeps the extra amount of ether after reaching its end state.

function test_lost_funds_over_misplaced_value() public {
    assertEq(address(line).balance, 0, "Line balance should be 0");
    assertEq(lender.balance, mintAmount, "lender should have initial mint balance");
    deal(borrower, 1 ether);

    console.log("\n1. initial state");
    console.log(address(line).balance); //  0
    console.log(lender.balance);        //  100000000000000000000
    console.log(borrower.balance);      //  1000000000000000000
    
    vm.startPrank(borrower);
    line.addCredit(dRate, fRate, 1 ether, Denominations.ETH, lender);
    vm.stopPrank();

    vm.startPrank(lender);
    line.addCredit{value: 2 ether}(dRate, fRate, 1 ether, Denominations.ETH, lender); //value does not match the agreed amount
    vm.stopPrank();
    bytes32 id = line.ids(0);
    assert(id != bytes32(0)); //confirms ok

    console.log("\n2. agreed credit but misplaced value");
    console.log(address(line).balance); //  2000000000000000000
    console.log(lender.balance);        //  98000000000000000000
    console.log(borrower.balance);      //  1000000000000000000

    vm.startPrank(borrower);
    line.borrow(id, 1 ether / 2);
    vm.stopPrank();

    console.log("\n3. borrower borrows 0.5 ether");
    console.log(address(line).balance); //  1500000000000000000
    console.log(lender.balance);        //  98000000000000000000
    console.log(borrower.balance);      //  1500000000000000000

    vm.startPrank(borrower);  
    line.depositAndClose{value: 1 ether / 2}(); //
    vm.stopPrank();
    
    console.log("\n4. borrower pays back 0.5 ether");
    console.log(address(line).balance); //  1000000000000000000
    console.log(lender.balance);        //  99000000000000000000
    console.log(borrower.balance);      //  1000000000000000000

    console.log("\nend state reached");                   
    console.log(uint(line.status()));           // 3
    console.log(uint(LineLib.STATUS.REPAID));   // 3
}

Tools Used

VSCode, Foundry

Recommended Mitigation Steps

Consider altering the check in L71 to:

    if(! (msg.value == amount) ) { revert TransferFailed(); } 

If for some reason there's a need to keep a margin in the amount received, set a reasonable constant to control it.

@code423n4 code423n4 added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working labels Nov 9, 2022
code423n4 added a commit that referenced this issue Nov 9, 2022
@c4-judge
Copy link
Contributor

dmvt marked the issue as duplicate of #25

@c4-judge
Copy link
Contributor

c4-judge commented Dec 6, 2022

dmvt marked the issue as satisfactory

@C4-Staff
Copy link
Contributor

liveactionllama marked the issue as duplicate of #39

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working duplicate-39 satisfactory Finding meets requirement
Projects
None yet
Development

No branches or pull requests

3 participants