SECTION 1: LEARNING OBJECTIVES
By the end of this lesson, you will be able to:
-
Define advanced smart contract patterns and their use cases.
-
Explain upgradeability patterns (proxy, diamond, eternal storage).
-
Understand access control patterns and role-based permissions.
-
Describe gas optimisation techniques for complex contracts.
-
Differentiate between standard and advanced security practices.
-
Identify common vulnerabilities in complex DeFi contracts.
-
Implement an upgradeable contract simulation in Python.
-
Develop a framework for secure smart contract architecture.
SECTION 2: ADVANCED SMART CONTRACT PATTERNS
2.1 Upgradeability Patterns
Smart contracts are immutable by default, but many projects require upgradeability for bug fixes, feature additions, and parameter adjustments. Several patterns enable upgradeability.
┌─────────────────────────────────────────────────────────────────────────────┐ │ UPGRADEABILITY PATTERNS │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ 1. PROXY PATTERN (Transparent Proxy) │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ • Separate logic (implementation) from storage (proxy) │ │ │ │ • Proxy delegates calls to implementation via delegatecall │ │ │ │ • Storage remains in proxy, logic can be upgraded │ │ │ │ • Example: OpenZeppelin TransparentUpgradeableProxy │ │ │ │ • Pros: Simple, widely adopted │ │ │ │ • Cons: Storage collisions, admin privileges │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ 2. UUPS (Universal Upgradeable Proxy Standard) │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ • Upgrade logic lives in the implementation contract │ │ │ │ • Proxy only handles delegation │ │ │ │ • Upgrades are triggered through the implementation │ │ │ │ • Examples: OpenZeppelin UUPSUpgradeable │ │ │ │ • Pros: More gas efficient, less storage risk │ │ │ │ • Cons: Upgrade logic must be in each implementation │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ 3. DIAMOND PATTERN (EIP-2535) │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ • Multiple implementation facets │ │ │ │ • Each facet handles a set of functions │ │ │ │ • Dynamic function routing │ │ │ │ • Example: Diamond proxy │ │ │ │ • Pros: Modular, flexible │ │ │ │ • Cons: Complex, harder to understand │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘
2.2 Access Control Patterns
| Pattern | Description | Use Case |
|---|---|---|
| Ownable | Single owner controls administrative functions | Simple contracts |
| Role-Based Access Control (RBAC) | Multiple roles with specific permissions | Complex systems |
| Multisig | Multiple signers required for actions | High-value operations |
| Timelock | Delay between proposal and execution | Governance |
| Emergency Stop | Pause functionality in emergencies | Security |
2.3 Gas Optimisation Patterns
| Pattern | Description | Benefit |
|---|---|---|
| Packed Variables | Use smaller data types (uint8, uint16) | Lower storage costs |
| Immutable Variables | Set at construction, never changed | Gas savings |
| Constants | Pre-defined constant values | No storage cost |
| Short Circuiting | Optimise conditional order | Reduced execution |
| Custom Errors | Use error strings with parameters | Less gas than require |
| Batch Operations | Process multiple actions in one call | Reduced overhead |
SECTION 3: ADVANCED SECURITY PRACTICES
3.1 Security Beyond Audits
| Practice | Description |
|---|---|
| Formal Verification | Mathematical proofs of contract properties |
| Fuzzing | Automated random input testing |
| Invariant Testing | Ensure key properties always hold |
| Bug Bounties | Incentivise external security researchers |
| Monitor and Alert | Real-time monitoring of contract activity |
| Emergency Response | Prepared incident response plan |
3.2 Common DeFi Vulnerabilities
| Vulnerability | Description | Example |
|---|---|---|
| Reentrancy | Recursive calls before state update | DAO hack |
| Price Manipulation | Manipulation of oracle prices | Mango Markets |
| Flash Loan Attacks | Exploiting uncollateralised loans | Various |
| Inflation Attacks | Manipulating token supply | ERC-4626 |
| Permission Issues | Missing access controls | Various |
| Front-Running | Transaction ordering exploitation | MEV |
| Sandwich Attacks | Exploiting AMM slippage | DEX trades |
3.3 Secure Development Lifecycle
┌─────────────────────────────────────────────────────────────────────────────┐ │ SECURE DEVELOPMENT LIFECYCLE │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ 1. DESIGN │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ • Threat modeling │ │ │ │ • Security requirements │ │ │ │ • Design review │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ 2. IMPLEMENTATION │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ • Follow secure coding practices │ │ │ │ • Use audited libraries │ │ │ │ • Code review │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ 3. TESTING │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ • Unit tests │ │ │ │ • Integration tests │ │ │ │ • Fuzzing │ │ │ │ • Formal verification │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ 4. AUDITING │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ • Internal review │ │ │ │ • External audit │ │ │ │ • Bug bounty │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ 5. DEPLOYMENT & MONITORING │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ • Deploy with monitoring │ │ │ │ • Incident response ready │ │ │ │ • Continuous security monitoring │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘
SECTION 4: IMPLEMENTATION IN PYTHON
# =================================================================== # MODULE 9, LESSON 1: ADVANCED SMART CONTRACT PATTERNS AND SECURITY # =================================================================== import hashlib import time from typing import Dict, List, Callable import warnings warnings.filterwarnings('ignore') print("="*70) print("ADVANCED SMART CONTRACT PATTERNS AND SECURITY") print("="*70) # ---------------------------------------------------------------- # PART A: PROXY PATTERN SIMULATION # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART A: Proxy Pattern Simulation") print("-"*60) class ProxyContract: """ Simulated proxy contract for upgradeability. """ def __init__(self): self.implementation = None self.storage = {} self.admin = "Admin" self.is_paused = False def set_implementation(self, address: str): if self.admin == "Admin": # Simplified check self.implementation = address print(f"Implementation set to {address}") def delegate_call(self, function: str, params: Dict) -> Dict: """Simulate delegatecall to implementation.""" if self.is_paused: return {'error': 'Contract paused'} # In a real proxy, this would call the implementation's function # Here we simulate the behavior if function == 'set_value': key = params.get('key') value = params.get('value') self.storage[key] = value return {'success': True, 'key': key, 'value': value} elif function == 'get_value': key = params.get('key') return {'key': key, 'value': self.storage.get(key)} return {'error': 'Function not found'} def pause(self): if self.admin == "Admin": self.is_paused = True print("Contract paused") def unpause(self): if self.admin == "Admin": self.is_paused = False print("Contract unpaused") def upgrade(self, new_implementation: str): """Upgrade to a new implementation.""" self.set_implementation(new_implementation) # Simulate proxy pattern proxy = ProxyContract() print("Proxy created") # Set initial implementation proxy.set_implementation("v1") # Interact with contract print("\nInteractions:") result = proxy.delegate_call('set_value', {'key': 'balance_alice', 'value': 1000}) print(f" set_value: {result}") result = proxy.delegate_call('get_value', {'key': 'balance_alice'}) print(f" get_value: {result}") # Upgrade implementation print("\nUpgrading to v2...") proxy.upgrade("v2") # Continue interactions (with new logic) result = proxy.delegate_call('set_value', {'key': 'balance_bob', 'value': 500}) print(f" set_value (v2): {result}") # Pause the contract proxy.pause() result = proxy.delegate_call('set_value', {'key': 'balance_charlie', 'value': 200}) print(f" set_value (paused): {result}") # Unpause and continue proxy.unpause() result = proxy.delegate_call('set_value', {'key': 'balance_charlie', 'value': 200}) print(f" set_value (unpaused): {result}") # ---------------------------------------------------------------- # PART B: ROLE-BASED ACCESS CONTROL SIMULATION # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART B: Role-Based Access Control Simulation") print("-"*60) class RoleBasedAccessControl: """ Simulated RBAC for smart contracts. """ def __init__(self): self.roles = { 'ADMIN': set(), 'OPERATOR': set(), 'USER': set() } self.functions = {} def grant_role(self, role: str, account: str): if role in self.roles: self.roles[role].add(account) print(f"Granted {role} to {account}") def revoke_role(self, role: str, account: str): if role in self.roles and account in self.roles[role]: self.roles[role].remove(account) print(f"Revoked {role} from {account}") def has_role(self, role: str, account: str) -> bool: return account in self.roles.get(role, set()) def check_access(self, account: str, function: str) -> bool: required_role = self.functions.get(function, 'USER') return self.has_role(required_role, account) def add_function(self, function: str, required_role: str): self.functions[function] = required_role # Create RBAC system rbac = RoleBasedAccessControl() # Add functions rbac.add_function('mint', 'ADMIN') rbac.add_function('pause', 'OPERATOR') rbac.add_function('transfer', 'USER') # Grant roles rbac.grant_role('ADMIN', '0xAlice') rbac.grant_role('OPERATOR', '0xBob') rbac.grant_role('USER', '0xCharlie') # Check access accounts = ['0xAlice', '0xBob', '0xCharlie', '0xDavid'] functions = ['mint', 'pause', 'transfer'] print("\nAccess Control Tests:") for account in accounts: for function in functions: access = rbac.check_access(account, function) status = "✅" if access else "❌" print(f" {status} {account} can call {function}") # ---------------------------------------------------------------- # PART C: SECURITY VULNERABILITY CHECKLIST # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART C: Security Vulnerability Checklist") print("-"*60) vulnerability_checklist = { "Reentrancy": [ "Are all external calls made after state updates?", "Is the Checks-Effects-Interactions pattern followed?" ], "Access Control": [ "Are all administrative functions properly protected?", "Is the modifier pattern used consistently?" ], "Arithmetic": [ "Is SafeMath used or Solidity 0.8+?", "Are there any unchecked arithmetic operations?" ], "Oracle": [ "Is the oracle source trusted?", "Are there multiple sources for critical data?" ], "Gas": [ "Are there any unbounded loops?", "Is gas optimisation considered?" ], "Upgradeability": [ "Is upgrade logic properly secured?", "Are storage collisions avoided?" ] } for category, checks in vulnerability_checklist.items(): print(f"\n{category.upper()}:") for check in checks: print(f" □ {check}") # ---------------------------------------------------------------- # PART D: SUMMARY AND RECOMMENDATIONS # ----------------------------------------------------------------- print("\n" + "="*70) print("PART D: Summary and Recommendations") print("="*70) print(""" Advanced Smart Contract Patterns and Security – Key Takeaways: 1. Upgradeability patterns: Proxy (Transparent), UUPS, Diamond (EIP-2535). 2. Proxy separates storage (proxy) from logic (implementation). 3. Role-Based Access Control (RBAC) for granular permissions. 4. Gas optimisation: packed variables, immutables, constants, short circuiting. 5. Security practices: formal verification, fuzzing, invariant testing, bug bounties. 6. Common vulnerabilities: reentrancy, price manipulation, flash loan attacks. 7. Secure development lifecycle: design → implementation → testing → audit → deployment. Recommendations: - Use established upgradeability patterns (OpenZeppelin). - Implement RBAC for complex systems. - Optimise gas for high-frequency functions. - Conduct formal verification for critical logic. - Monitor contracts in production. - Have an incident response plan ready. """) print("="*70) print("END OF LESSON 1 – MODULE 9") print("="*70)