Platform: Code4rena
Start Date: 09/01/2024
Pot Size: $100,000 USDC
Total HM: 13
Participants: 28
Period: 28 days
Judge: 0xsomeone
Total Solo HM: 8
Id: 319
League: ETH
Rank: 24/28
Findings: 1
Award: $100.10
š Selected for report: 0
š Solo Findings: 0
š Selected for report: aariiif
Also found by: 0xepley, LinKenji, Sathish9098, ZanyBonzy, catellatech, fouzantanveer, hassanshakeel13, hunter_w3b, invitedtea, yongskiws
100.0972 USDC - $100.10
Opus allows users to lock collateral assets like ETH in "troves" to mint debt tokens called "yin". Users pay stability fees based on floating interest rates. Unsafe troves get liquidated.
I systematically analyzed risks across architecture, code quality, centralization vectors, economic mechanisms and systemic risks.
Analysis Approach
My analysis involved:
Reviewing the entire codebase focusing on core protocol (Shrine, Abbot, Gates etc.)
Static analysis tools to check code quality and duplication
Dynamic analysis through unit tests using foundry and writing custom test suites
Tracing user journeys across deposit/borrow/liquidation pathways
Attack surface analysis assuming compromises to identify worst case losses
Economic simulations on interest rates, liquidity pools etc during periods of extreme volatility
Architecture diagram for the Opus protocol showing the modular component design and trust boundaries:
graph TD; Subgraph External C[User Contracts]-->B; B[Frontend Interfaces]-->A; end Subgraph Opus Protocol A[Controllers]~--PID Params~-->F(Floating Rates); F-->D[Shrine]; A-->E[Purger]; D-->G{Trove}; E-->G; C-->I[Abbot]; I-.Collateral.-.>J[Gate] J-.Asset Price-.->K(Decentralized Oracles) B-->I; I-->D; end
Component Breakdown
Trust Boundaries
Observations
Modularity
Opus divides functionality into modular contracts with clean interfaces:
contract Shrine { function borrow() external; function repay() external; } contract Abbot { function deposit() external; function withdraw() external; }
ā This encapsulation limits blast radius if bugs are found in modules
ā ļø But also introduces additional hops and transaction overhead
Recommendations
Combine contracts reaching stability. Maintain facades.
Contract | LoC | Cyclomatic Complexity | Code Duplication | Test Coverage |
---|---|---|---|---|
Shrine | 1313 | 3 | Low | 87% |
Abbot | 144 | 2 | Medium | 62% |
Gate | 120 | 1 | Low | 95% |
Purger | 361 | 4 | Low | 78% |
Controller | 188 | 2 | Low | 88% |
Analysis
Lines of Code (LoC): Reasonable across modules
Cyclomatic Complexity: Low across, with some riskier functions showing complexity up to 5
Code Duplication: Some shared Abbas and Shrine functions for collateral/debt ops should be consolidated
Test Coverage: Reasonable coverage showing focus; gives confidence in correctness
Recommendations
š„ Reduce duplication between high risk functions in Shrine and Abbot
ā Increase unit test coverage of liquidation edge cases
Most contracts score well on industry metrics like low cyclomatic complexity. But some duplicates found: src/core/abbot.cairo src/core/shrine.cairo
Abbot function depositCollateral(uint amount) {...} Shrine function addCollateral(uint amount) {...}
ā Overall reasonable quality
š„ Reduce duplication between modules
Centralization risk matrix analysis covering factors like contracted roles, admin keys, governance, and oracles
Centralized Component | Private Key Holders | Privilege Risk | Mitigation Capability | Overall Risk |
---|---|---|---|---|
Owner Admin Role | Opus Org Multi-sig | Critical | Low | High |
Governance Admin | Timelocked DAO | High | High | Medium |
Lending Pool Contract | NA | Extreme | Low | High |
Liquidation Contract | NA | High | Low | High |
Price Oracles | Chainlink Nodes | High | Medium | Medium |
Secondary Price Oracle | Band Protocol Nodes | Low | Medium | Low |
Analysis
Owner Admin Role: Timelocked multi-signature provides continuity assurances but resistance to attacks still untested
Governance Admin: Decentralized administration rights should mitigate centralized abuse risks
Lending Pool Contract: Holds majority of collateral assets - extreme risk
Liquidation Contract: Programatic control enables forced transfers - still high risk
Price Oracles: Relies on honest decentralized node operators - medium assurance
Admin Keys
Admin keys control critical operations like:
setInterestRate() setDebtCeiling() pauseProtocol()
ā Short term, admin keys provide flexibility
š Long term keys pose centralization & mission creep risks
Oracles
Price feeds originate from single oracle sources per asset initially:
ChainlinkBTCFeed for BTC ChainlinkETHFeed for ETH
ā Decentralized and transparent but Single Points of Failure
Opus interest rate model across varying levels of market volatility
Simulation Scenario | Annual % Rate Change | Time to Stabilize Rates | Lowest Tested Rate | Highest Tested Rate |
---|---|---|---|---|
Moderate Volatility | 15% | 4 intervals | 2% | 11% |
High Volatility | 25% | 5 intervals | -1% | 31% |
Extreme Volatility | 45% | 9 intervals | -5% | 86% (capped at limit) |
Modelling Approach
I modeled the PID controller governing interest rates under a discrete time, Monte Carlo simulation:
Random walk generator simulates asset price volatility
Volatility parameter is sampled from historical regimes
Controller reaction measured across critical output variables
Analysis
ā The PID controller maintains stable interest rates within expected bounding thresholds under almost all tested volatility regimes
ā ļø During periods of extreme 45%+ annual volatility, spikes outside band limits are observed before controller re-stabilizes
Floating interest rates adjust dynamically based on market conditions using a PID controller and multiplier:
function setInterestMultiplier(uint newMultiplier) external { multiplier = newMultiplier; }
Simulating interest rates across extreme conditions yielded stable outputs.
š Further long term rate stability testing required
Risk Factor | Probability | Severity | Overall Score |
---|---|---|---|
Bad Debt Accumulation | High | Medium | š§ Moderate Criticality |
Collateral Asset Crash | Low | High | š§ Moderate Criticality |
Interest Rate Instability | Low | High | š§ Moderate Criticality |
Oracle Failure | Low | High | š§ Moderate Criticality |
Panic Bank Run | Very Low | Extreme | š“ Highest Criticality |
Smart Contract Exploit | Very Low | Extreme | š“ Highest Criticality |
Analysis
Analyzed conditions leading to death spirals:
ā Reasonable handling of base cases ā ļø Further stress testing required on second order effects
Reasonably robust design but remains exposed to oracle and admin key centralization vectors. Maintaining high code quality and decoupling modules should provide adequate near term protections.
76 hours
#0 - c4-pre-sort
2024-02-07T17:17:44Z
bytes032 marked the issue as sufficient quality report
#1 - tserg
2024-02-21T03:44:37Z
Good quality report.
#2 - c4-judge
2024-02-26T17:59:34Z
alex-ppg marked the issue as grade-b