Debt DAO contest - carlitox477's results

A cryptonative credit marketplace for fully anon and trustless loans to DAOs.

General Information

Platform: Code4rena

Start Date: 03/11/2022

Pot Size: $115,500 USDC

Total HM: 17

Participants: 120

Period: 7 days

Judge: LSDan

Total Solo HM: 1

Id: 174

League: ETH

Debt DAO

Findings Distribution

Researcher Performance

Rank: 69/120

Findings: 3

Award: $70.73

QA:
grade-b

🌟 Selected for report: 0

πŸš€ Solo Findings: 0

Awards

4.0405 USDC - $4.04

Labels

bug
2 (Med Risk)
downgraded by judge
partial-50
duplicate-39

External Links

Lines of code

https://github.com/debtdao/Line-of-Credit/blob/6987988fe39901cad9a8e5ebb2c6aa719590873d/contracts/utils/LineLib.sol#L71 https://github.com/debtdao/Line-of-Credit/blob/6987988fe39901cad9a8e5ebb2c6aa719590873d/contracts/modules/credit/LineOfCredit.sol#L237 https://github.com/debtdao/Line-of-Credit/blob/6987988fe39901cad9a8e5ebb2c6aa719590873d/contracts/modules/credit/LineOfCredit.sol#L280 https://github.com/debtdao/Line-of-Credit/blob/6987988fe39901cad9a8e5ebb2c6aa719590873d/contracts/modules/credit/LineOfCredit.sol#L305 https://github.com/debtdao/Line-of-Credit/blob/6987988fe39901cad9a8e5ebb2c6aa719590873d/contracts/modules/credit/LineOfCredit.sol#L330 https://github.com/debtdao/Line-of-Credit/blob/6987988fe39901cad9a8e5ebb2c6aa719590873d/contracts/modules/credit/LineOfCredit.sol#L401

Vulnerability details

Impact

Function LineLib.receiveTokenOrETH is used in LineOfCredit.addCredit; LineOfCredit.increaseCredit; LineOfCredit.depositAndClose; LineOfCredit.depositAndRepay; LineOfCredit.close; LineOfCredit.depositAndRepay; LineOfCredit.close. When we try to receive ETH, this can mess up accountability, because it allows to deposit more ETH than the one indicated as amount. Then this ETH would be stuck in the contract

POC

  1. Borrower call function LineOfCredit.addCredit(1,1,1,0,Denominations.ETH,lender)
  2. Lender calls function LineOfCredit.addCredit{value:2}(1,1,1,0,Denominations.ETH,lender)

The function succeed but the extra ETH sent is not recoverable, it will remain stuck in the contract.

Mitigation steps

Check amount == msg.value in LineLib.sendOutTokenOrETH function

#0 - c4-judge

2022-11-17T11:12:35Z

dmvt marked the issue as duplicate of #25

#1 - c4-judge

2022-11-17T19:34:41Z

dmvt changed the severity to 2 (Med Risk)

#2 - c4-judge

2022-11-17T19:34:46Z

dmvt marked the issue as partial-50

#3 - carlitox477

2022-12-07T21:06:28Z

I beg to disagree with the partial-50 label:

  • The selected report points out exactly the same functions of LineOfCredit:
    1. Borrower calls depositAndClose with an ETH value that is above the owed debt. is indicated in the impact section
    2. Borrower calls depositAndRepay with an ETH value that is above the amount specified in the parameters. is indicated in the impact section
    3. Borrower calls close with an ETH value that is above the owed fees. indicated in the impact section
    4. Lender calls addCredit with and ETH value that is greater than the amount parameter. indicated in the impact section
    5. Lender calls increaseCredit with and ETH value that is greater than the amount parameter indicated in the impact section
    6. Excessive ETH will be sent (and expected to be refunded) when calling depositeAndClose(), close(id) and depositAndRepay(amount) indicated in the impact section.
  • The mittigation step pointed out in this issue is the same than in the selected report revert - change the expression if(msg.value < amount) to if(msg.value != amount) and revert the transaction.
  • This report was graded as satisfactory, with far less detail about how to exploit the vulnerability (no mentio which functions are related to receiveTokenOrETH())
  • This report indicates almost the same POC than mine and judged as satisfactory
  • This report indicate the same mittigation step I suggest, just writen different

I beg the judge to reconsider grading this report as satisfactory

#4 - dmvt

2022-12-09T09:39:04Z

#5 - C4-Staff

2022-12-20T06:44:51Z

liveactionllama marked the issue as duplicate of #39

Awards

5.3388 USDC - $5.34

Labels

bug
2 (Med Risk)
satisfactory
duplicate-369

External Links

Lines of code

https://github.com/debtdao/Line-of-Credit/blob/6987988fe39901cad9a8e5ebb2c6aa719590873d/contracts/utils/LineLib.sol#L48

Vulnerability details

Impact

Classic C4 issue

The use of the deprecated transfer() function for an address will inevitably make the transaction fail when:

  1. The recipient smart contract does not implement a payable function.
  2. The recipient smart contract does implement a payable fallback which uses more than 2300 gas unit.
  3. The recipient smart contract implements a payable fallback function that needs less than 2300 gas units but is called through proxy, raising the call’s gas usage above 2300.

Additionally, using higher than 2300 gas might be mandatory for some multisig wallets.

POC

https://code4rena.com/reports/2022-04-backd/#m-01-call-should-be-used-instead-of-transfer-on-an-address-payable

It is recommended using call() instead of transfer().

#0 - c4-judge

2022-11-17T11:15:33Z

dmvt marked the issue as duplicate of #14

#1 - c4-judge

2022-11-17T19:19:31Z

dmvt marked the issue as partial-50

#2 - c4-judge

2022-12-06T14:55:27Z

dmvt marked the issue as full credit

#3 - c4-judge

2022-12-06T14:55:31Z

dmvt marked the issue as satisfactory

#4 - C4-Staff

2022-12-20T05:56:43Z

liveactionllama marked the issue as duplicate of #369

LineOfCredit#constructor: Lack of zero addess check

Next state variable can be set to zero:

Mitigation steps: Add next lines inside constructor:

if (oracle_ == address(0) || arbiter_ == address(0) || borrower_ = address(0)){revert ERROR_ZERO_ADDRESS();} // Create error ERROR_ZERO_ADDRESS()

It must be said that if arbitrer is equal to zero address, then function declareInsolvent would be uncallable

SpigotLib#updateOwnerSplit can emmit redundant event

It does not check if the previous owner split is equal the the new owner split, leading to redundant event emission. The function should be changed to:

function updateOwnerSplit(SpigotState storage self, address revenueContract, uint8 ownerSplit)
    external
    returns(bool)
{
    if(msg.sender != self.owner) { revert CallerAccessDenied(); }
    if(ownerSplit > MAX_SPLIT) { revert BadSetting(); }
    require(self.settings[revenueContract].ownerSplit != ownerSplit);

    self.settings[revenueContract].ownerSplit = ownerSplit;
    emit UpdateOwnerSplit(revenueContract, ownerSplit);
    
    return true;
}

SpigotLib owner change should be done in to steps

To avoid mistakenly transfer the owner role to a wrong address, it would be recommendable to divide the owner role transfer in two function. The first one only callable for the current owner to set the pending owner, and the second one only callable by the pending owner to claim their role as owner.

SpigotLib#updateOwner can emmit redundant event

It does not check if the previous owner is equal the the new owner address, leading to redundant event emission. The function should be changed to:

function updateOwner(SpigotState storage self, address newOwner) external returns (bool) {
    if(msg.sender != self.owner) { revert CallerAccessDenied(); }
    require(newOwner != address(0));
    require(newOwner != self.owner);
    self.owner = newOwner;
    emit UpdateOwner(newOwner);
    return true;
}

SpigotLib operator change should be done in to steps

To avoid mistakenly transfer the operator role to a wrong address, it would be recommendable to divide the operator role transfer in two function. The first one only callable for the current operator to set the pending operator, and the second one only callable by the pending operator to claim their role as operator.

SpigotLib#updateOperator can emmit redundant event

It does not check if the previous operator is equal the the new operator address, leading to redundant event emission. The function should be changed to:

function updateOperator(SpigotState storage self, address newOperator) external returns (bool) {
    if(msg.sender != self.operator) { revert CallerAccessDenied(); }
    require(newOperator != address(0));
    require(self.operator != newOperator);
    self.operator = newOperator;
    emit UpdateOperator(newOperator);
    return true;
}

SpigotLib#updateWhitelistedFunction can emmit redundant event

It does not check if the previous treasury is equal the the new treasury address, leading to redundant event emission. The function should be changed to:

function updateTreasury(SpigotState storage self, address newTreasury) external returns (bool) {
    if(msg.sender != self.operator && msg.sender != self.treasury) {
        revert CallerAccessDenied();
    }

    require(newTreasury != address(0));
    require(newTreasury != self.treasury);
    self.treasury = newTreasury;
    emit UpdateTreasury(newTreasury);
    return true;
}

SpigotLib#updateWhitelistedFunction can emmit redundant event

It does not check if the function was previously whitelisted or not, leading to redundant event emission. The function should be changed to:

function updateWhitelistedFunction(SpigotState storage self, bytes4 func, bool allowed) external returns (bool) {
    if(msg.sender != self.owner) {
        revert CallerAccessDenied();
    }
    if(self.whitelistedFunctions[func] != allowed){
        self.whitelistedFunctions[func] = allowed;
        emit UpdateWhitelistFunction(func, allowed);
        return true;
    }
    return false
}

InterestRateCredit: INTEREST_DENOMINATOR should be immutable

Giving that is set through a calculation, INTEREST_DENOMINATOR should be immutable

SpigotedLine: Lack of zero address check could lead to redeployment

The constructor does not check if spigot_ and swapTarget_ are diferent from zero address.

Oracle#constructor: registry can be set to address zero

Doing this would leave the contract useless, needing to redeploy it.

#0 - c4-judge

2022-12-06T21:27:46Z

dmvt marked the issue as grade-b

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax Β© 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter