I’ve been building on Ethereum since 2017, and I want to push back on something I keep hearing: “OWASP SC10 proves upgradeable contracts are bad.”
No. SC10 proves INSECURELY IMPLEMENTED upgradeable contracts are bad. There’s a huge difference.
Why Developers Need Upgradeability
Let me be blunt: immutable contracts are a luxury most teams can’t afford.
When you’re building a complex DeFi protocol with 15+ interconnected contracts, the idea that you’ll get everything perfect on the first deploy is fantasy. Not because you’re a bad developer—because the problem space is inherently complex.
Real-world challenges I’ve faced:
1. Bug fixes that couldn’t wait for governance
Discovered a critical vulnerability in our staking contract 3 days after mainnet launch. If it were immutable, we’d have had to:
- Launch a new contract
- Migrate all user funds (requiring them to approve and migrate)
- Lose TVL during migration
- Risk users not migrating and losing access to funds
Instead: Emergency upgrade via multi-sig, vulnerability patched in 6 hours, zero user disruption.
2. Protocol evolution based on user feedback
Our initial tokenomics had a parameter that made yield farming inefficient. Users complained. In an immutable world, we’d have to:
- Deploy entirely new contracts
- Convince all liquidity providers to migrate
- Fragment liquidity between old and new versions
- Watch competitors capture market share while we rebuild
With upgradeability: Governance vote, parameter adjustment, users happy.
3. Regulatory compliance requirements
When MiCA regulations hit Europe, we needed to add KYC hooks for EU users. Immutable contracts would have forced us to:
- Abandon the European market (20% of our users)
- Deploy a parallel EU-compliant version (fragmenting liquidity)
- Lose competitive position to protocols that could adapt
Upgradeability let us add compliance layers without disrupting existing users.
The Real Issue: Implementation Quality, Not Concept
OWASP SC10 isn’t saying “don’t use proxies.” It’s saying “implement them correctly.”
Common mistakes I see (and how to avoid them):
Storage collisions → Use OpenZeppelin’s standardized storage patterns
Uninitialized proxies → Always use initializer modifiers, disable initialize on implementation
Unrestricted upgrades → Multi-sig + timelock (minimum 48 hours)
Delegatecall confusion → Use UUPS or Transparent Proxy patterns, not custom logic
These aren’t rocket science. They’re well-documented patterns.
The Decentralization Spectrum
Here’s my controversial take: the immutable = decentralized narrative is oversimplified.
Consider these scenarios:
Scenario A: Immutable contract with admin emergency shutdown
- Can’t upgrade logic
- BUT admin can pause the protocol anytime
- Is this really “trustless”?
Scenario B: Upgradeable contract with 7-day timelock + community veto
- Can upgrade with governance approval
- Community has 7 days to exit if they disagree
- Transparent upgrade history on-chain
Which is MORE decentralized?
I’d argue Scenario B. Transparency + exit rights > false immutability.
Progressive Decentralization Is The Real Answer
Most successful protocols follow this path:
Phase 1 (Months 0-6): Team multi-sig, fast upgrades
- Need to iterate quickly
- Bug fixes without governance delay
- 2-of-3 multi-sig with 24-hour timelock
Phase 2 (Months 6-18): Governance-gated upgrades
- Community votes on major changes
- 5-of-9 multi-sig with 48-hour timelock
- Emergency pause requires 7-of-9
Phase 3 (18+ months): Full decentralization
- All upgrades require token holder vote
- 7-day timelock minimum
- Eventually: Renounce upgrade ability entirely (if protocol is stable)
This lets teams move fast early (when most bugs are discovered) while progressively reducing trust assumptions.
What About Formal Verification?
The immutability argument often goes: “Just formally verify before deployment!”
As someone who’s actually TRIED formal verification on production contracts:
- It’s expensive: $200K+ for comprehensive verification
- It’s slow: 3-6 months for complex protocols
- It’s incomplete: Can’t verify business logic, only code correctness
- It doesn’t cover upgrades: Even verified contracts need parameter adjustments
Formal verification is GREAT for critical components (consensus, cryptography). But it’s not a replacement for iterative development.
The Real Security Improvement
Want to know what would ACTUALLY improve security?
Not banning upgradeability—but standardizing upgrade governance.
If every protocol used:
- Minimum 7-day timelocks
- Multi-sig with geographic distribution
- Transparent upgrade logs
- Emergency pause separate from upgrade authority
- Regular security council audits of upgrade processes
Then SC10 would barely exist as a category.
My Ask To The Community
Stop treating upgradeability as a dirty word. Treat INSECURE upgradeability as the enemy.
Questions for discussion:
- Should OWASP publish “secure upgrade pattern” reference implementations?
- Is there a minimum timelock duration we should standardize (24h? 48h? 7 days)?
- How do we balance “move fast and fix bugs” with “give users exit time”?
- For mature protocols, when is it safe to renounce upgrade ability?
The goal is trustless systems. Sometimes the path there requires trust minimization, not trust elimination.