Platform: Code4rena
Start Date: 29/04/2021
Pot Size: $30,000 USDC
Total HM: 3
Participants: 6
Period: 6 days
Judge: cemozer
Total Solo HM: 2
Id: 7
League: ETH
Rank: 4/6
Findings: 1
Award: $4,523.84
🌟 Selected for report: 6
🚀 Solo Findings: 0
669.6429 BLO - $133.93
401.7857 USDC - $401.79
0xRajeev
Six of the seven Comptroller verify functions do nothing. Not sure why their calls in CToken.sol have been uncommented from the original Compound version.
Except redeemVerify(), six other verify functions transferVerify(), mintVerify(), borrowVerify(), repayBorrowVerify(), liquidateBorrowVerify() and seizeVerify() have no logic except accessing state variables to not be marked pure. Calls to these functions were commented out in the original Compound code’s CToken.sol but have been uncommented here.
Given that they do not implement any logic, the protocol should not be making any assumptions about any defence provided from their unimplemented verification logic.
Dummy functions whose comments say “// Shh - currently unused”:
Uncommented calls from modified code:
Commented calls from original Compound code:
Manual Analysis
Add logic to implement verification if that is indeed assumed to be implemented but is actually not. Otherwise, comment call sites.
#0 - ghoul-sol
2021-05-07T17:45:04Z
Fixed by commenting unused functions.
669.6429 BLO - $133.93
401.7857 USDC - $401.79
0xRajeev
The sweepToken() function in the original Compound code whose specified purpose was to recover accidentally sent ERC20 tokens to contract has been removed.
The original code comment says: “A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock).” This safety measure is helpful given the number/value of accidentally stuck tokens that are sent to contracts by mistake.
Tokens accidentally sent to this contract will be stuck leading to fund loss for sender.
Manual Analysis
Retain this function unless there is a specific reason to remove it here.
#0 - ghoul-sol
2021-05-08T21:42:40Z
Fixed as recommended, thanks!
🌟 Selected for report: 0xRajeev
1488.0952 BLO - $297.62
892.8571 USDC - $892.86
0xRajeev
Contracts should be deployed using the same compiler version/flags with which they have been tested. Locking the floating pragma, i.e. by not using ^ in pragma solidity ^0.6.10, ensures that contracts do not accidentally get deployed using an older compiler version with unfixed bugs.
For reference, see https://swcregistry.io/docs/SWC-103
Manual Analysis
Remove ^ in “pragma solidity ^0.6.10” and change it to “pragma solidity 0.6.12” to be consistent with the rest of the contracts.
#0 - ghoul-sol
2021-05-08T00:48:38Z
Fixed as recommended.
🌟 Selected for report: 0xRajeev
Also found by: toastedsteaksandwich
669.6429 BLO - $133.93
401.7857 USDC - $401.79
0xRajeev
Function _setCompAddress() is used by admin to change the COMP token address. However, there is no zero-address validation on the parameter. This may accidentally set COMP token address to zero-address but it can be reset by the admin. Any interim transactions might hit exceptional behavior.
Manual Analysis
Add zero-address check to _comp parameter of _setCompAddress().
#0 - ghoul-sol
2021-05-08T16:49:23Z
Duplicate of #14
🌟 Selected for report: 0xRajeev
1488.0952 BLO - $297.62
892.8571 USDC - $892.86
0xRajeev
A zero or some minimum threshold check is missing for newMaxAssets parameter of _setMaxAssets() function which is used by admin to set the maximum number of assets that controls how many markets can be entered.
If accidentally set to 0 then all users cannot enter any market which will significantly affect protocol operations.
Manual Analysis
Add zero/threshold check to newMaxAssets parameter.
#0 - ghoul-sol
2021-05-08T17:04:53Z
Added to backlog, however, it's a non-critical issue.
#1 - cemozerr
2021-05-12T02:44:09Z
Rating this as low risk as it could pose a situation where users can not enter any markets.
669.6429 BLO - $133.93
401.7857 USDC - $401.79
0xRajeev
Low-level calls call/delegatecall/staticcall return true even if the account called is non-existent (per EVM design). Account existence must be checked prior to calling.
The doTransferOut() function was changed from using a transfer() function (which reverts) to a call() function (which returns a boolean), however there is no account existence check for the destination address to. If it doesn’t exist, for some reason, call will still return true (not throw an exception) and successfully pass the return value check on the next line.
The checked call paths don’t seem vulnerable because they use msg.sender/admin and not a user-controlled address, but this may be a risk if used later in other contexts. Hence rating as low-risk.
For reference, see this related high-risk severity finding from Trail of Bit’s audit of Hermez Network: https://github.com/trailofbits/publications/blob/master/reviews/hermez.pdf
https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls
Manual Analysis
Check for account-existence before the call() to make this safely extendable to user-controlled address contexts in future.
#0 - ghoul-sol
2021-05-05T15:04:02Z
Recommended fix has been implemented.