Zum Inhalt

08 - Blockchain-Integration

Dokument: On-Chain-Architektur & Smart Contracts Stand: 28.02.2026 Scope: Arbitrum Sepolia, Smart Contracts, EIP-712, VRF Status: Audit-ready


1. Netzwerk-Konfiguration

Parameter Wert
Netzwerk Arbitrum Sepolia (L2 Testnet)
Chain ID 421614 (0x66eee)
RPC Endpoint Alchemy (arb-sepolia.g.alchemy.com/v2/[KEY])
WebSocket Alchemy (wss://arb-sepolia.g.alchemy.com/v2/[KEY])
Block Explorer https://sepolia.arbiscan.io
Gas Token ETH
Zahlungsmittel USDT (6 Decimals)

RPC-Fallback

Priorität URL
Primary NEXT_PUBLIC_RPC_URL (Alchemy)
Fallback https://sepolia-rollup.arbitrum.io/rpc

2. Deployed Smart Contracts

Contract Adresse Version Funktion
GameManager 0x5FcCADaE2d4F19314cf110f869b897454482e583 V3 Ticket-Kauf-Logik
USDT Token 0x594Cf4b2eeF269B1733296F84C7dcf7271852fb1 ERC-20 Zahlungsmittel (6 Dec)
ReserveVault 0x53660d0d3199D8186bf285f42c39ab3319CFda83 V2 USDT-Halter, Approval-Empfänger
GameTreasury 0x9999C145A468d1f310619Fe91c2daAB9799bd883 V2 Buchhaltung, Einzahlungs-Events
Settlement 0x27341819551cD8E51923B93f51f36c11bD614835 V5 Tägliche Abrechnung, Payout-Orchestrierung
PrizeVault 0x39E1fc95205d94C69a1cf2E8958373B5B255A610 V3 Merkle-basierte Winner Claims
AffiliateVault 0x7b489D221843016794e88FC003E85E90ac00283c V2 Affiliate-Provisionen
ClaimRouter 0x7038bbf08649DB63253c0c20267329EEf7F33722 V2 Batch-Claim-Ausführung
CharityVault 0x95E70C06eAAA753d1493638DE20A138ee299d193 - Charity-Gelder
VRF Receiver 0xAB16BC9996a26277A988499882aAfcEcFB6606ea V3 Chainlink VRF Empfänger
VRF Coordinator 0x5ce8d5a2bc84beb22a398cca51996f7930313d61 - Chainlink VRF Coordinator
Multicall3 0xcA11bde05977b3631167028862bE2a173976CA11 - Batch-RPC-Calls

3. Pool-Konfiguration

Pool ID Name Preis/Tip USDT (6 Dec)
0 Micro 0,25 USDT 250.000
1 Mini 0,50 USDT 500.000
2 Standard 1,00 USDT 1.000.000
3 Maxi 5,00 USDT 5.000.000
4 Ultra 10,00 USDT 10.000.000

Parameter Wert
Coordinator 0x5ce8d5a2bc84beb22a398cca51996f7930313d61
Key Hash 0x1770bdc7eec7771f7ba4ffd640f34260d7f095b79c92d34a5b2551d6f6cfd2be
Subscription ID 620136758604089751630200059125847364...
Empfänger VRFReceiverV3

Quad-Source-Randomness

Die Plattform verwendet 4 Zufallsquellen:

Quelle Beschreibung
Chainlink VRF On-chain verifiable random function
drand Distributed randomness beacon
Block Hash Ethereum block hash
Backend Signatur Server-seitige Signatur

5. EIP-712 Typed Data Signaturen

5.1 BuyPermit

Domain:

name: "ChainbetsGame"
version: "1"
chainId: 421614
verifyingContract: GameManager

Types:

BuyPermit {
  buyer: address
  poolId: uint256
  tipsHash: bytes32
  deadline: uint256
  nonce: uint256
  maxGasCostUsdt: uint256
}

5.2 ClaimPermit

Domain:

name: "ChainbetsClaim"
version: "1"
chainId: 421614
verifyingContract: ClaimRouter

Types:

ClaimPermit {
  claimer: address
  totalWinnerAmount: uint256
  totalAffiliateAmount: uint256
  maxGasCostUsdt: uint256
  deadline: uint256
  nonce: bytes32
  claimsHash: bytes32
}

5.3 Permit-Deadlines

Typ Default Beschreibung
BuyPermit Backend-generiert Deadline im Intent gesetzt
ClaimPermit 5 Minuten calculateDeadline(5)

6. Smart-Contract-Interaktionen

6.1 Ticket-Kauf

GameManager.buyTicketFor(
  address buyer,
  uint256 tipCount,
  uint256 bonusTipCount,
  address affiliate,
  BuyPermit permit,
  bytes signature,
  bytes extraBonusProof,
  uint256 gasCostUsdt
)

Events: - TicketCreated(uint256 ticketId, address player, uint8[] rngNumbers) - Deposited(address player, uint256 dayId, uint8 poolId, uint256 amount, ...)

6.2 Gewinn-Claiming

ClaimRouter.claimAllFor(
  ClaimPermit permit,
  bytes signature,
  WinnerClaim[] winnerClaims,
  AffiliateClaim[] affiliateClaims,
  uint256 actualGasCostUsdt
)

6.3 USDT-Approval

USDT.approve(address spender, uint256 amount)
// spender = ReserveVault (Buy) oder ClaimRouter (Claim)
// amount = type(uint256).max

6.4 Merkle-Claiming (direkt)

PrizeVaultV3.claimMerkle(
  uint256 dayId,
  address originalWallet,
  address paidTo,
  uint256 amount,
  bytes32[] proof
)

AffiliateVaultV2.claimAffiliate(
  uint256 dayId,
  address affiliate,
  address to,
  uint256 amount,
  bytes32[] proof
)

7. Relayer-System

7.1 Konfiguration

Parameter Beschreibung
Adresse RELAYER_ADDRESS (= OPERATOR)
Private Key RELAYER_PK
Funktion Sendet TXs im Auftrag der Nutzer
Gas-Bezahlung Relayer zahlt ETH-Gas, wird in USDT erstattet

7.2 Gasless UX

User signiert EIP-712 Permit
  → Backend erstellt TX mit Relayer-Wallet
  → Relayer sendet TX on-chain
  → Gas-Kosten werden in USDT vom Nutzer-Guthaben abgezogen
  → Nutzer zahlt nie direkt ETH

7.3 Gas-Faucet (Ausnahme: Erst-Approval)

Für die erste USDT-Approval benötigt der Nutzer ETH:

POST /api/buy/gas-faucet
  → Backend prüft Berechtigung
  → Sendet ETH an Nutzer-Wallet
  → Nutzer kann approve() Transaktion senden
  → Faucet-Kosten werden beim nächsten Kauf verrechnet


8. Contract-Versionen & Migrationen

Datei: lib/contractVersions.ts

Bei Contract-Upgrades werden Claims über verschiedene Versionen verwaltet:

interface ContractVersion {
  settlement_address: string;
  prize_vault_address: string;
  affiliate_vault_address: string;
  claim_router_address: string;
  reserve_vault_address: string;
}

DB-Tabelle: contract_versions(from_day_id, to_day_id, addresses...)

Claim-Gruppierung: groupClaimsByVersion(dayIds) ordnet Claims den korrekten Contract-Versionen zu.


9. Wallet-Integration

9.1 ethers.js v6

  • BrowserProvider für Web3Auth Provider
  • Signer für Transaktions-Signierung
  • JsonRpcProvider als Fallback für Read-Only-Calls
  • Contract für Smart-Contract-Interaktionen

9.2 Balance-Abfragen

// ETH Balance
const balance = await provider.getBalance(address);
const formatted = ethers.formatEther(balance);

// USDT Balance
const usdt = new Contract(USDT_ADDRESS, ["function balanceOf(address) view returns (uint256)"], provider);
const raw = await usdt.balanceOf(address);
const formatted = (Number(raw) / 1_000_000).toFixed(2);

Weiterführende Dokumente: - 05 - Buy Flow - 06 - Claim Flow - 10 - Sicherheit