Platform: Code4rena
Start Date: 14/06/2022
Pot Size: $100,000 USDC
Total HM: 26
Participants: 59
Period: 7 days
Judge: GalloDaSballo
Total Solo HM: 9
Id: 133
League: ETH
Rank: 7/59
Findings: 5
Award: $4,096.71
π Selected for report: 2
π Solo Findings: 4
π Selected for report: cryptphi
978.304 USDC - $978.30
6057.6098 CANTO - $978.30
AccountantDelegate.initialize() is missing a zero address check for treasury_
parameter, which could may allow treasury to be mistakenly set to 0 address.
Manual review
Add a require() check for zero address for the treasury parameter before changing the treasury address in the initialize function.
#0 - GalloDaSballo
2022-08-12T00:42:04Z
Because:
treasury
variable is only set on the initializerI'm going to mark the finding as valid and of Medium severity.
In mentioning this report in the future, notice that the conditions that caused me to raise the severity weren't simply the lack of a check, but the actual risk of loss of funds, and the inability to easily fix
π Selected for report: cryptphi
978.304 USDC - $978.30
6057.6098 CANTO - $978.30
https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/CNote.sol#L14-L21 https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/CNote.sol#L31 https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/CNote.sol#L96 https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/CNote.sol#L178 https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/CNote.sol#L258
In CNote._setAccountantContract() , the require() check only works when address(_accountant) != address(0)
, leading to the ability to set _accountant
state variable to the zero address, as well as setting admin to zero address.
The following below are impacts arising from above:
mintFresh()
then calling redeemFresh()
_setAccountantContract()
with parameter input as 0.mintFresh()
with input address 0 and mintAmount 1000. (assuming function is external, reporting a separate issue on the mutability)if (minter == address(_accountant))
and proceeds to mint 1000 CTokens to address(0)redeemFresh()
with her address as the redeemer
parameter, and redeemTokensIn as 1000.A user can borrow CToken asset from the contract, then set _accountant to 0 after. With _accountant being set to 0 , the borrower , then call repayBorrowFresh()
to have _accountant (address 0) to repay back the borrowed tokens assuming address(0) already has some tokens, and user's borrowed asset (all/part) are repaid.
borrowFresh()
to borrow 500 CTokens from contract._setAccountantContract()
with parameter input as 0.repayBorrowFresh()
having the payer be address 0, borrower being her address and 500 as repayAmount.When the _accountant is set to 0, CTokens/CNote will be sent to the zero address making the Accounting contract lose funds whenever doTransferOut
is called.
Manual review
Instead of a if (address(_accountant) != address(0))
statement, an additional require check to ensure accountant_
parameter is not 0 address can be used in addition to the require check for caller is admin.
Change this
require(msg.sender == admin, "CNote::_setAccountantContract:Only admin may call this function"); }
to this
require(msg.sender == admin, "CNote::_setAccountantContract:Only admin may call this function"); require(accountant_ != address(0), "accoutant can't be zero address");
#0 - GalloDaSballo
2022-08-07T21:04:43Z
The warden has shown how, due to a misconfiguration, if the accountant
is set to 0, users will be able to extra additional value (repay tokens for free).
Because this is contingent on a misconfiguration, I believe Medium Severity to be more appropriate
π Selected for report: joestakey
Also found by: 0x1f8b, 0x29A, 0x52, 0xDjango, 0xNazgul, 0xf15ers, 0xmint, Bronicle, Dravee, Funen, JMukesh, Limbooo, MadWookie, Picodes, Ruhum, TerrierLover, TomJ, Tutturu, WatchPug, Waze, _Adam, asutorufos, c3phas, catchup, cccz, codexploder, cryptphi, csanuragjain, defsec, fatherOfBlocks, gzeon, hake, hansfriese, hyh, ignacio, k, nxrblsrpr, oyc_109, robee, sach1r0, saian, simon135, technicallyty, zzzitron
72.3997 USDC - $72.40
687.9945 CANTO - $111.11
https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/Comptroller.sol#L1380 https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/Accountant/AccountantDelegate.sol#L87 https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/Accountant/AccountantDelegate.sol#L89 https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/Treasury/TreasuryDelegate.sol#L52 https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/Treasury/TreasuryDelegate.sol#L56 https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/CErc20.sol#L128 https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/CEther.sol#L150 https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/Treasury/TreasuryDelegate.sol#L52 https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/Treasury/TreasuryDelegate.sol#L56
Multiple calls to transfer are frequently done without checking the results. For certain ERC20 tokens, if insufficient tokens are present, no revert occurs but a result of βfalseβ is returned. Itβs important to check this, users or admin could gain or lose tokens if return value of transfer() is not checked.
The following functions are affected: Comptroller.grantCompInternal() - https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/Comptroller.sol#L1380 AccountantDelegate.sweepInterest() - https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/Accountant/AccountantDelegate.sol#L87 AccountantDelegate.sweepInterest() - https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/Accountant/AccountantDelegate.sol#L89 TreasuryDelegate.sendFund() - https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/Treasury/TreasuryDelegate.sol#L52 TreasuryDelegate.sendFund() - https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/Treasury/TreasuryDelegate.sol#L56 CErc20.sweepToken() - https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/CErc20.sol#L128 CEther.doTransferOut() - https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/CEther.sol#L150 TreasuryDelegate.sendFund() - https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/Treasury/TreasuryDelegate.sol#L52 TreasuryDelegate.sendFund() - https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/Treasury/TreasuryDelegate.sol#L56
Slither and manual review
Check the returned values of transfers or use a SafeERC20 transfer.
#0 - GalloDaSballo
2022-08-05T01:32:07Z
Dowgrading to QA for now.
Disagree with all the ERC20 safeTransfer recommendation as the impl is known (note) and the token reverts on failure.
Agree with checking result of eth.transfer