Compound
Summary
ExpandThe Compound Protocol V2 is a well-established, battle-tested lending and borrowing protocol that implements a sophisticated delegator/delegate proxy pattern for upgradeability, a Comptroller for centralized risk management and policy enforcement, and a governance system (Governor Alpha/Bravo) backed by a Timelock for all privileged administrative actions. The architecture separates concerns cleanly: cToken contracts handle individual market logic, the Comptroller enforces cross-market invariants such as collateral requirements and liquidation eligibility, and the governance layer ensures that parameter changes pass through a time-delayed execution window. The protocol handles non-standard ERC-20 tokens via assembly-level return data inspection, a design decision that reflects awareness of real-world token implementation inconsistencies.
The audit identified 4 findings across the codebase: 1 medium-severity and 3 low-severity issues. The most significant finding is M-1, a gas-limited ETH transfer in CEther's use of `.transfer()` that imposes a 2300 gas stipend, which can cause denial-of-service for smart contract wallet recipients whose receive functions exceed that budget. The three low-severity findings address missing input validation and unchecked return values: L-1 identifies that close factor bounds validation constants are defined but never enforced in the Comptroller's setter function, while L-2 and L-3 flag unchecked ERC-20 transfer return values in the Reservoir contract and the `sweepToken` function respectively, where a silently failing transfer could result in tokens not being moved as expected. None of these findings create paths for direct fund theft, but each represents a gap in the protocol's defense-in-depth posture.
The codebase demonstrates strong security engineering throughout. The custom `nonReentrant` modifier protects all state-modifying user-facing functions, interest accrual freshness checks prevent operations on stale state, and the checks-effects-interactions pattern is consistently applied. The Comptroller correctly uses `msg.sender` rather than a caller-supplied parameter for the seizer cToken identity during liquidation, preventing collateral seizure spoofing. The two-step admin transfer pattern across governance contracts prevents accidental or irreversible loss of administrative control, and the Comptroller's liquidity calculation properly handles hypothetical positions to prevent under-collateralized borrows.
Findings
1 issue identified
CEther uses .transfer() with 2300 gas limit, causing DoS for smart contract recipients
contracts/CEther.sol:144
View Details
Description
CEther.doTransferOut uses Solidity’s .transfer() to send ETH, which forwards only 2300 gas. Post-Istanbul, this is insufficient for many smart contract wallets (Gnosis Safe, proxy wallets, account abstraction). This function is called during redeem, borrow, and reduceReserves. Smart contract users who hold cETH may be permanently unable to redeem their underlying ETH.
Impact
Smart contract wallets that supplied ETH cannot redeem cETH. Borrowers using smart contract wallets cannot receive borrowed ETH. Funds are effectively frozen for affected users.
Recommendation
Replace .transfer() with .call{value:}() with return value checking. This is safe because all calling functions already use the nonReentrant modifier.
Fix
Using .call{value:}() forwards all available gas instead of the 2300 gas limit of .transfer(). Reentrancy is already mitigated by the nonReentrant modifier on all calling functions and the checks-effects-interactions pattern (state updates occur before the external call).
contracts/CEther.sol
Conclusion
ExpandThe Compound Protocol V2 codebase reflects a mature and carefully engineered system. The consistent application of reentrancy guards, freshness checks, checks-effects-interactions ordering, and time-locked governance demonstrates a development team with deep understanding of DeFi-specific attack surfaces. Code quality is high, with clear separation of concerns between market logic, risk policy, and governance, and the proxy upgradeability pattern is implemented correctly with storage layout discipline.
The most actionable finding is M-1, the use of .transfer() in CEther, which is a well-documented Solidity pattern that creates compatibility risk as the smart contract wallet ecosystem grows — particularly relevant given EIP-1884’s repricing of the SLOAD opcode. While not a fund-theft vulnerability, it can lock smart contract users out of receiving ETH from the protocol. The missing bounds validation in L-1 is notable because the validation constants closeFactorMinMantissa and closeFactorMaxMantissa exist in the codebase but are never enforced, suggesting the checks were inadvertently omitted rather than intentionally excluded. The unchecked transfer return values in L-2 and L-3, while low-risk given that the affected tokens are typically governance-controlled, violate the defensive programming principles otherwise evident throughout the codebase.
Overall, the protocol is well-suited for continued mainnet operation. The 4 identified issues are low-to-medium severity and do not compromise the core lending, borrowing, or liquidation logic. Remediating M-1 by replacing .transfer() with a low-level .call{value: amount}("") pattern, enforcing the existing bounds constants in L-1, and adding return value checks for L-2 and L-3 would close the remaining gaps and bring these components in line with the high standard of defensive engineering demonstrated elsewhere in the protocol.
Legal Disclaimer: This report covers the code submitted for analysis. It does not account for infrastructure, deployment configuration, third-party dependencies, or changes made after the audit date. Automated analysis may produce false positives or miss context-dependent vulnerabilities. audited.xyz provides this report “as is” without warranty of any kind.