11 - Sicherheit & Access Control¶
Defense Layers, Threat Model, Emergency Procedures
Defense Layers¶
Das System implementiert 6 Verteidigungsebenen:
Layer 1: Access Control (Rollentrennung)¶
| Rolle | Verantwortung | Kann NICHT |
|---|---|---|
| SAFE (Owner) | Konfiguration, Emergency, Withdraw | Operatoren-Aktionen, spezifische Claims |
| Operator | VRF Request, Settlement, Wallet-Reassignment | Funds zugreifen, Fee-Splits ändern |
| Settlement | Payout-Autorisierung | Funds halten, Konfiguration ändern |
| Relayer | Batch Claims ausführen | Funds abzweigen (nur operatorFeeReceiver) |
| Spieler | Claim via Merkle Proof | Merkle-Verifizierung umgehen |
Layer 2: One-Time Setters¶
Kritische Contract-Referenzen können nur einmal gesetzt werden:
function setSettlement(address _settlement) external onlyOwner {
require(settlement == address(0), "Already set");
settlement = _settlement;
}
Layer 3: Fund Segregation (Option B)¶
┌──────────────────────────────┐
│ ReserveVault (hält USDT) │ ← Einziger Fund Holder
├──────────────────────────────┤
│ CharityVault (hält USDT) │ ← Sekundärer Fund Holder
├──────────────────────────────┤
│ Alle anderen Contracts │ ← State only, KEIN USDT
└──────────────────────────────┘
Layer 4: Merkle Verification¶
- Gewinner und Affiliates müssen kryptografische Proofs vorlegen
- Roots sind immutable (einmal gesetzt, nie änderbar)
- Double-Claim Prevention via
claimedMapping
Layer 5: Reentrancy Guards¶
Alle payout-relevanten Funktionen nutzen OpenZeppelin ReentrancyGuard:
function payPrize(...) external onlyAuthorizedSettlement nonReentrant
function claimMerkle(...) external nonReentrant
function claimAllFor(...) external onlyRelayer nonReentrant
Layer 6: Emergency Controls¶
emergencyModeauf ReserveVault blockiert alle PayoutsforceMarkDaySettledlöst Settlement-Deadlocks- Operator-Key-Rotation über 4 Contracts
- VRF Receiver-Rotation möglich
Vollständige Access Control Matrix¶
ReserveVaultV2¶
| Funktion | SAFE | Settlement | Treasury | Anyone |
|---|---|---|---|---|
| depositFrom | - | - | - | ✅ |
| payPrize | - | ✅ | - | - |
| payFee | - | ✅ | - | - |
| payCharity | - | ✅ | - | - |
| payOperatorFee | - | - | ✅ | - |
| setEmergencyMode | ✅ | - | - | - |
| ownerWithdraw | ✅ | - | - | - |
GameManagerV3¶
| Funktion | SAFE | Operator | VRFReceiver |
|---|---|---|---|
| buyTicketFor | - | ✅ | - |
| setVrfSeed | ✅ | - | ✅ |
| setDrandSeed | - | ✅ | - |
| setOperator | ✅ | - | - |
| setPoolUsesVRF | ✅ | - | - |
SettlementV5¶
| Funktion | SAFE | Operator | PrizeVault | AffiliateVault |
|---|---|---|---|---|
| commitMerkleSettlement | - | ✅ | - | - |
| payoutFromPrizeVault | - | - | ✅ | - |
| payoutFromAffiliateVault | - | - | - | ✅ |
| forceMarkDaySettled | ✅ | - | - | - |
PrizeVaultV3¶
| Funktion | SAFE | Operator | Settlement | TrustedClaimer | Spieler |
|---|---|---|---|---|---|
| claimMerkle | - | - | - | ✅ | ✅ (eigene) |
| adminReassignWallet | - | ✅ | - | - | - |
| setMerkleRootForDay | - | - | ✅ | - | - |
ClaimRouterV2¶
| Funktion | SAFE | Relayer |
|---|---|---|
| claimAllFor | - | ✅ |
| setRelayer | ✅ | - |
| setMaxGasCap | ✅ | - |
Threat Model¶
| Bedrohung | Wahrscheinlichkeit | Impact | Mitigation |
|---|---|---|---|
| Operator Key Kompromittiert | Mittel | Hoch | Key-Rotation, SAFE bleibt sicher, Settlement-Validierung |
| SAFE Key Kompromittiert | Niedrig | Kritisch | Multisig (mehrere Signaturen nötig) |
| Merkle Root Manipulation | Niedrig | Kritisch | Root nur vom Settlement setzbar, immutable |
| VRF DoS | Mittel | Mittel | try/catch, prevrandao Fallback |
| Reentrancy Angriff | Niedrig | Hoch | ReentrancyGuard auf allen Payouts |
| Flash Loan Angriff | N/A | N/A | Kein DeFi-Composability (USDT nur) |
| Signature Replay | Niedrig | Hoch | Nonce + Deadline + Chain ID |
| Fund Drain via Logic Bug | Niedrig | Kritisch | Fund Segregation, Emergency Mode |
Emergency Procedures¶
1. Emergency Mode aktivieren¶
Situation: Verdacht auf Exploit oder kritischer Bug
Aktion: SAFE aktiviert Emergency Mode auf ReserveVault
SAFE → ReserveVaultV2.setEmergencyMode(true)
Effekt:
✅ Alle Payouts blockiert (payPrize, payFee, payCharity, payOperatorFee)
✅ Deposits weiterhin möglich
✅ ownerWithdraw() funktioniert (Fund Recovery)
❌ Settlement kann nicht committen (Payouts reverieren)
❌ Claims können nicht ausgeführt werden
Dauer: ~5 Minuten (SAFE Multisig Signatur-Sammlung)
2. Settlement Deadlock auflösen¶
Situation: Tag X hat Tickets aber Backend kann nicht settlen
Aktion: SAFE markiert Tag als settled (ohne Merkle Root)
SAFE → SettlementV5.forceMarkDaySettled(dayId)
Effekt:
✅ daySettled[dayId] = true
✅ Nächster Tag kann Tickets verkaufen
❌ Keine Merkle Roots gesetzt (Spieler für diesen Tag verlieren Gewinne)
❌ Keine Fee Splits ausgeführt
Verwendung: Nur als absoluter Notfall!
3. Operator Key Rotation¶
Situation: Operator-Key kompromittiert oder Mitarbeiter-Wechsel
Aktion: Neuen Operator auf allen relevanten Contracts setzen
SAFE Batch-Transaktion:
1. GameManagerV3.setOperator(newOperator)
2. SettlementV5.setOperator(newOperator)
3. PrizeVaultV3.setOperator(newOperator)
4. VRFReceiverV3.setOperator(newOperator)
Effekt: Alter Operator verliert sofort alle Berechtigungen
4. VRF Receiver Rotation¶
Situation: VRF Receiver muss aktualisiert werden
Aktion: Neuen VRFReceiver deployen und verdrahten
1. Deploy: new VRFReceiverV3(coordinator, keyHash, subId, gameManager, operator, lastSeed)
2. SAFE: GameManagerV3.setVrfReceiver(newReceiver) (falls One-Time-Setter erlaubt)
3. Chainlink: Neuen Consumer zur Subscription hinzufügen
4. Alten Consumer entfernen
Invarianten für Audit-Prüfung¶
Ökonomische Invarianten¶
-
Balance Conservation:
-
Payout Bounds:
-
Fee Split:
-
Merkle Claims:
State-Invarianten¶
-
Settlement Sequentialität:
-
Merkle Root Immutability:
-
Nonce Uniqueness:
-
Double-Claim Prevention:
Audit-Hinweise¶
Kritischste Angriffsfläche
Die größte Gefahr ist ein Bug im Settlement-Commit, der falsche Merkle Roots setzt. Da Roots immutable sind, wäre das nicht rückgängig zu machen. Die Korrektheit wird off-chain sichergestellt.
SAFE ist Single Point of Trust
Der SAFE-Owner hat ultimative Kontrolle (Emergency, Withdraw, Konfiguration). Die Sicherheit des gesamten Systems hängt von der SAFE-Sicherheit ab.
Kein Proxy/Upgrade Pattern
Die Contracts nutzen keine Proxy-Pattern (kein UUPS, kein TransparentProxy). Upgrades erfolgen durch Deploy + Re-Wiring. Das ist sicherer aber aufwändiger.