contract-patterns.md
1 # Alpha/Delta Smart Contract Security Patterns 2 3 Generated: 2026-01-08 4 Source: components/security.cspec (S001) 5 Version: 1.0.0 6 7 ## Overview 8 9 This document defines security patterns for smart contracts on the Alpha/Delta Protocol, covering both AlphaVM (privacy-focused) and DeltaVM (exchange-focused) environments. 10 11 --- 12 13 ## 1. Language Security (ADL) 14 15 ### 1.1 Alpha Delta Language (ADL) 16 17 ADL is the contract language for Alpha/Delta, derived from Leo with additional safety features. 18 19 | Feature | Security Benefit | 20 |---------|-----------------| 21 | Static typing | Prevents type confusion attacks | 22 | Ownership model | Prevents unauthorized access | 23 | Bounded types | Prevents overflow/underflow | 24 | Private by default | Functions/data hidden unless explicit | 25 26 ### 1.2 Compiler Guarantees 27 28 | Check | Description | Enforced At | 29 |-------|-------------|-------------| 30 | Type safety | All operations type-checked | Compile time | 31 | Bounds checking | Array access verified | Compile time + Runtime | 32 | Ownership verification | Resource tracking | Compile time | 33 | ZK circuit validation | Proof generation verified | Compile time | 34 35 --- 36 37 ## 2. Reentrancy Protection 38 39 ### 2.1 The Problem 40 41 Reentrancy occurs when external calls allow re-entry before state updates complete. 42 43 ``` 44 Vulnerable Pattern: 45 1. Check balance (passes) 46 2. External call (attacker re-enters) 47 3. Update balance (never reached in first call) 48 ``` 49 50 ### 2.2 Checks-Effects-Interactions (CEI) 51 52 **Pattern**: Perform checks, update state, then make external calls. 53 54 ``` 55 // CORRECT: CEI Pattern 56 function withdraw(amount: u64) { 57 // 1. CHECKS 58 assert(balances[caller] >= amount); 59 60 // 2. EFFECTS (state changes) 61 balances[caller] -= amount; 62 63 // 3. INTERACTIONS (external calls) 64 transfer(caller, amount); 65 } 66 ``` 67 68 ``` 69 // WRONG: Interactions before effects 70 function withdraw_vulnerable(amount: u64) { 71 assert(balances[caller] >= amount); 72 transfer(caller, amount); // External call BEFORE state update 73 balances[caller] -= amount; // Never reached on reentry 74 } 75 ``` 76 77 ### 2.3 Reentrancy Guard 78 79 For complex cases, use a mutex pattern: 80 81 ``` 82 state { 83 locked: bool = false; 84 } 85 86 modifier nonReentrant() { 87 assert(!locked, "Reentrancy detected"); 88 locked = true; 89 _; // Execute function 90 locked = false; 91 } 92 93 function sensitiveOperation() with nonReentrant { 94 // Safe from reentrancy 95 } 96 ``` 97 98 ### 2.4 ADL Reentrancy Protection 99 100 ADL provides built-in reentrancy protection: 101 102 | Feature | Mechanism | 103 |---------|-----------| 104 | Single-entry enforcement | Runtime lock on contract entry | 105 | Async call isolation | External calls complete before return | 106 | State snapshot | Rollback on failure | 107 108 --- 109 110 ## 3. Integer Safety 111 112 ### 3.1 The Problem 113 114 Integer overflow/underflow can bypass critical checks. 115 116 ``` 117 // Overflow example (in languages without protection): 118 uint256 max = 2^256 - 1; 119 uint256 overflow = max + 1; // Wraps to 0! 120 ``` 121 122 ### 3.2 Safe Math in ADL 123 124 ADL uses bounded types that prevent overflow: 125 126 | Type | Range | Overflow Behavior | 127 |------|-------|------------------| 128 | u8 | 0 to 255 | Compile error or runtime panic | 129 | u16 | 0 to 65,535 | Compile error or runtime panic | 130 | u32 | 0 to 4,294,967,295 | Compile error or runtime panic | 131 | u64 | 0 to 18,446,744,073,709,551,615 | Compile error or runtime panic | 132 | u128 | 0 to 2^128-1 | Compile error or runtime panic | 133 134 ### 3.3 Checked Operations 135 136 ``` 137 // ADL automatically uses checked arithmetic 138 function safe_add(a: u64, b: u64) -> u64 { 139 return a + b; // Panics on overflow 140 } 141 142 // Explicit overflow handling 143 function safe_add_checked(a: u64, b: u64) -> Option<u64> { 144 return a.checked_add(b); // Returns None on overflow 145 } 146 ``` 147 148 ### 3.4 Token Amount Handling 149 150 | Practice | Description | 151 |----------|-------------| 152 | Use u128 for totals | Prevent overflow in aggregations | 153 | Validate before operations | Check bounds explicitly | 154 | Use decimals consistently | AX: 4 decimals, DX: 0 decimals | 155 156 --- 157 158 ## 4. Oracle Manipulation Protection 159 160 ### 4.1 The Problem 161 162 Price oracles can be manipulated to exploit contracts. 163 164 ``` 165 Attack scenario: 166 1. Manipulate oracle price (flash loan, low liquidity) 167 2. Execute contract using manipulated price 168 3. Profit from price discrepancy 169 4. Oracle returns to normal 170 ``` 171 172 ### 4.2 Time-Weighted Average Price (TWAP) 173 174 Use time-averaged prices to resist manipulation: 175 176 ``` 177 struct PriceOracle { 178 cumulative_price: u128, 179 last_update: u64, 180 twap_period: u64, // e.g., 30 minutes 181 } 182 183 function get_twap_price(oracle: PriceOracle) -> u64 { 184 let time_elapsed = now() - oracle.last_update; 185 assert(time_elapsed >= oracle.twap_period, "TWAP period not met"); 186 187 let current_cumulative = get_cumulative_price(); 188 let price_delta = current_cumulative - oracle.cumulative_price; 189 190 return price_delta / time_elapsed; 191 } 192 ``` 193 194 ### 4.3 Multi-Source Validation 195 196 Aggregate prices from multiple sources: 197 198 ``` 199 function get_validated_price(sources: Vec<PriceSource>) -> u64 { 200 assert(sources.len() >= 3, "Minimum 3 sources required"); 201 202 let prices: Vec<u64> = sources.map(|s| s.get_price()); 203 204 // Remove outliers (> 5% deviation from median) 205 let median = calculate_median(prices); 206 let valid_prices = prices.filter(|p| 207 abs_diff(*p, median) <= median / 20 208 ); 209 210 assert(valid_prices.len() >= 2, "Insufficient valid prices"); 211 212 return calculate_average(valid_prices); 213 } 214 ``` 215 216 ### 4.4 Circuit Breakers 217 218 Pause operations when prices are suspicious: 219 220 | Condition | Action | 221 |-----------|--------| 222 | Price change > 10% in 1 block | Pause, require manual review | 223 | Oracle not updated > 1 hour | Use stale price flag | 224 | Source disagreement > 5% | Pause until resolution | 225 226 --- 227 228 ## 5. Access Control Patterns 229 230 ### 5.1 Ownership Model 231 232 ``` 233 state { 234 owner: Address, 235 admins: Set<Address>, 236 } 237 238 modifier onlyOwner() { 239 assert(caller == owner, "Not owner"); 240 _; 241 } 242 243 modifier onlyAdmin() { 244 assert(admins.contains(caller) || caller == owner, "Not admin"); 245 _; 246 } 247 ``` 248 249 ### 5.2 Role-Based Access Control (RBAC) 250 251 ``` 252 enum Role { 253 None, 254 Operator, 255 Manager, 256 Admin, 257 } 258 259 state { 260 roles: Map<Address, Role>, 261 } 262 263 function has_role(addr: Address, required: Role) -> bool { 264 let user_role = roles.get(addr).unwrap_or(Role::None); 265 return user_role >= required; 266 } 267 268 modifier requireRole(required: Role) { 269 assert(has_role(caller, required), "Insufficient role"); 270 _; 271 } 272 ``` 273 274 ### 5.3 Timelock for Critical Operations 275 276 ``` 277 struct PendingAction { 278 action_hash: Hash, 279 execute_after: u64, 280 executed: bool, 281 } 282 283 state { 284 pending_actions: Map<Hash, PendingAction>, 285 timelock_delay: u64 = 48 * 3600, // 48 hours 286 } 287 288 function propose_action(action_hash: Hash) with onlyAdmin { 289 pending_actions.insert(action_hash, PendingAction { 290 action_hash, 291 execute_after: now() + timelock_delay, 292 executed: false, 293 }); 294 } 295 296 function execute_action(action_hash: Hash) with onlyAdmin { 297 let action = pending_actions.get_mut(action_hash).unwrap(); 298 assert(now() >= action.execute_after, "Timelock not expired"); 299 assert(!action.executed, "Already executed"); 300 301 action.executed = true; 302 // Execute the action 303 } 304 ``` 305 306 --- 307 308 ## 6. Privacy-Specific Patterns (AlphaVM) 309 310 ### 6.1 Record-Based State 311 312 AlphaVM uses a record (UTXO) model for privacy: 313 314 ``` 315 record Token { 316 owner: Address, 317 amount: u64, 318 // Private fields hidden in ZK proofs 319 } 320 321 // Consuming records reveals only serial numbers 322 function transfer(input: Token, to: Address, amount: u64) -> (Token, Token) { 323 assert(input.amount >= amount, "Insufficient balance"); 324 325 let output_to = Token { owner: to, amount: amount }; 326 let output_change = Token { owner: input.owner, amount: input.amount - amount }; 327 328 return (output_to, output_change); 329 } 330 ``` 331 332 ### 6.2 ZK Proof Verification 333 334 | Check | Purpose | 335 |-------|---------| 336 | Proof validity | Cryptographic verification | 337 | Serial number uniqueness | Prevent double-spend | 338 | Commitment consistency | State transition validity | 339 340 ### 6.3 Privacy Leaks to Avoid 341 342 | Leak Vector | Mitigation | 343 |-------------|------------| 344 | Transaction timing | Add random delays | 345 | Amount patterns | Use fixed denominations | 346 | Address reuse | Generate new addresses per transaction | 347 | Metadata | Strip unnecessary transaction data | 348 349 --- 350 351 ## 7. DEX-Specific Patterns (DeltaVM) 352 353 ### 7.1 Order Matching Security 354 355 ``` 356 struct Order { 357 maker: Address, 358 pair: (Token, Token), 359 price: u64, 360 amount: u64, 361 expiry: u64, 362 nonce: u64, 363 signature: Signature, 364 } 365 366 function verify_order(order: Order) -> bool { 367 // Check expiry 368 assert(now() < order.expiry, "Order expired"); 369 370 // Verify signature 371 let message = hash(order.maker, order.pair, order.price, order.amount, order.expiry, order.nonce); 372 assert(verify_signature(order.signature, message, order.maker), "Invalid signature"); 373 374 // Check nonce not used 375 assert(!used_nonces.contains((order.maker, order.nonce)), "Nonce reused"); 376 377 return true; 378 } 379 ``` 380 381 ### 7.2 Frontrunning Protection 382 383 | Technique | Description | 384 |-----------|-------------| 385 | Commit-reveal | Hide order details until execution | 386 | Private transactions | Use ZK to hide pending orders | 387 | Batch auctions | Process orders in batches | 388 | Maximum slippage | User-defined price bounds | 389 390 ### 7.3 Liquidity Pool Security 391 392 ``` 393 function swap( 394 pool: LiquidityPool, 395 token_in: Token, 396 amount_in: u64, 397 min_amount_out: u64 // Slippage protection 398 ) -> u64 { 399 let amount_out = calculate_output(pool, token_in, amount_in); 400 401 // Slippage protection 402 assert(amount_out >= min_amount_out, "Slippage exceeded"); 403 404 // CEI: Update state before transfer 405 update_pool_reserves(pool, token_in, amount_in, amount_out); 406 407 // Transfer tokens 408 transfer_from(caller, pool.address, token_in, amount_in); 409 transfer(caller, other_token(pool, token_in), amount_out); 410 411 return amount_out; 412 } 413 ``` 414 415 --- 416 417 ## 8. Testing Requirements 418 419 ### 8.1 Unit Tests 420 421 | Test Category | Coverage Target | 422 |---------------|-----------------| 423 | Access control | 100% | 424 | Math operations | 100% | 425 | State transitions | 100% | 426 | Error conditions | 100% | 427 428 ### 8.2 Fuzzing 429 430 | Target | Fuzzer | 431 |--------|--------| 432 | Input validation | Property-based testing | 433 | Arithmetic | Overflow/underflow cases | 434 | State machines | Invariant testing | 435 436 ### 8.3 Formal Verification 437 438 | Property | Verification Method | 439 |----------|-------------------| 440 | No unauthorized minting | Symbolic execution | 441 | Balance conservation | Theorem proving | 442 | Access control invariants | Model checking | 443 444 --- 445 446 ## 9. Deployment Checklist 447 448 ### Pre-Deployment 449 450 - [ ] All tests passing (unit, integration, fuzz) 451 - [ ] Code review by 2+ developers 452 - [ ] External audit for high-value contracts 453 - [ ] Deployment script reviewed 454 - [ ] Upgrade path documented (if applicable) 455 456 ### Post-Deployment 457 458 - [ ] Verify deployed bytecode matches source 459 - [ ] Verify constructor parameters 460 - [ ] Monitor for unusual activity 461 - [ ] Document deployment transaction 462 463 --- 464 465 ## References 466 467 - S001_threat_model (components/security.cspec) 468 - ADL Compiler (components/alpha/A002-adl.component.cspec) 469 - Attack Vectors (docs/security/attack-vectors.md) 470 - DeltaVM Specification (components/delta/D001-deltavm.component.cspec)