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
Rank: 69/120
Findings: 3
Award: $70.73
π Selected for report: 0
π Solo Findings: 0
π Selected for report: 0xdeadbeef0x
Also found by: 8olidity, Ch_301, HE1M, Koolex, Lambda, Nyx, RedOneN, Ruhum, Tomo, Trust, adriro, aphak5010, ayeslick, berndartmueller, brgltd, carlitox477, cccz, codexploder, d3e4, eierina, eighty, immeas, joestakey, lotux, minhquanym, perseverancesuccess, rbserver, rvierdiiev
4.0405 USDC - $4.04
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
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
LineOfCredit.addCredit(1,1,1,0,Denominations.ETH,lender)
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.
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:
receiveTokenOrETH()
)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
π Selected for report: __141345__
Also found by: 0xdeadbeef0x, 8olidity, Amithuddar, Bnke0x0, Ch_301, Deivitto, IllIllI, KingNFT, Nyx, RaymondFam, RedOneN, Satyam_Sharma, SmartSek, Tomo, adriro, bananasboys, carlitox477, cccz, cloudjunky, codexploder, corerouter, cryptonue, d3e4, datapunk, joestakey, martin, merlin, minhquanym, pashov, peanuts, rvierdiiev
5.3388 USDC - $5.34
Classic C4 issue
The use of the deprecated transfer() function for an address will inevitably make the transaction fail when:
Additionally, using higher than 2300 gas might be mandatory for some multisig wallets.
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
π Selected for report: IllIllI
Also found by: 0x1f8b, 0xNazgul, 0xRoxas, 0xSmartContract, Awesome, Aymen0909, B2, BClabs, Bnke0x0, Deekshith99, Deivitto, Diana, Dinesh11G, Funen, HE1M, HardlyCodeMan, Josiah, Nyx, Rahoz, RaymondFam, RedOneN, ReyAdmirado, Rolezn, Saintcode_, TomJ, Trust, __141345__, a12jmx, adriro, ajtra, aphak5010, apostle0x01, brgltd, btk, bulej93, c3phas, carlitox477, catwhiskeys, ch0bu, chaduke, chrisdior4, cryptonue, cryptostellar5, csanuragjain, ctf_sec, delfin454000, djxploit, durianSausage, erictee, fatherOfBlocks, gogo, i_got_hacked, immeas, joestakey, jumpdest7d, lukris02, martin, mcwildy, merlin, minhquanym, oyc_109, pashov, peanuts, pedr02b2, rbserver, rotcivegaf, rvierdiiev, sakman, saneryee, seyni, shark, slowmoses, tnevler, trustindistrust, w0Lfrum, yurahod, zaskoh
61.3462 USDC - $61.35
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
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; }
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.
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; }
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.
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; }
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; }
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 }
Giving that is set through a calculation, INTEREST_DENOMINATOR
should be immutable
The constructor does not check if spigot_
and swapTarget_
are diferent from zero address.
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