System Architecture
Tscrow is a Hybrid Decentralized Protocol. While funds are secured by immutable smart contracts, the user experience is coordinated by a high-performance Telegram backend. This page explains the architecture that ensures these two worlds remain in perfect sync.
High-Level Components
Telegram Bot: The interface users interact with. It manages the state of the "deal" before it goes on-chain
VaultFactory (Smart Contract): A singleton contract responsible for deploying individual Tscrow Vaults. It ensures that every vault is created with the correct, immutable parameters
Tscrow Vault (Smart Contract): A single-use, disposable smart contract created for exactly one deal and one purpose. It holds the funds and enforces the logic.
Relayer (The Bot): Pays gas fees, submits all contract calls, (vault deployment, deal actions, disputes, etc.)
The Coordination Lifecycle
Intent Capture: When a user creates a deal, the bot captures metadata (amount, chain, buyer/seller address) in Firestore.
Deterministic Binding: The bot uses
CREATE2to calculate the vault address. This address is shown to the user instantly, before any on-chain transaction occurs.Autonomous Monitoring: A background service watches these predicted addresses for deposits.
Relayer Execution: Once funds are detected, the bot's relayer wallet deploys the contract and initializes its on-chain state, syncing it with the off-chain database.
Guardrails
Handling high-volume P2P trades requires preventing "double-action" errors (e.g., trying to release and refund at the same time). Tscrow implements a Triple-Lock defense:
Memory-Level Mutex: The bot uses per-deal mutexes within the server to prevent concurrent logic execution for the same transaction.
Database Transactions: All critical state changes (Joining, Confirming Fiat) happen inside Firestore transactions.
Execution Lease: When an on-chain action (like
release()) is triggered, the bot sets a "In-Progress" lock. This prevents redundant transactions during blockchain congestion.
The "Self-Healing" Layer
No system is perfect, and blockchain RPCs can fail. Tscrow includes a "Self-Healing" subsystem to handle these edge cases: Safe Fallbacks If an RPC returns invalid gas data, the system falls back to a safe, pre-configured minimum to prevent "stuck" transactions
Transaction Recovery
If the bot crashes after sending a transaction but before updating the database, the Recovery Service scans for "Pending" transactions on startup. It verifies their status on the blockchain and "finishes" the database update if the transaction succeeded.
State Reconciliation
The Reconciliation Service periodically compares every active deal's on-chain status with its database status. If a user interacts with the contract directly (bypassing the bot), the bot detects the change and updates its UI to reflect both parties.
Architecture Diagram
Key Technologies
CREATE2 Deterministic Deployment
We use the CREATE2 opcode to generate vault addresses. This is critical for security.
Before Deployment: We can tell you exactly what the vault address will be based on the deal parameters (Buyer, Seller, Amount, Token)
Verification: You can verify that the address provided by the bot actually matches the promise in the smart contract.
Safety: The vault cannot be deployed with different parameters at that address. It is mathematically bound to the deal details.
Single-Use Vault Architecture
Tscrow does not pool user funds into a single contract. Instead, each deal is isolated inside its own dedicated vault contract.
This design has important security advantages:
Risk Isolation: Each vault holds funds for only one deal. A failure or issue in one vault cannot affect any other deal.
Reduced Attack Surface: There is no large pooled balance that can be targeted as a single high-value attack.
Auditable Simplicity: Each vault contains minimal and purpose specific logic, making it easier to reason about, review, and audit compared to complex pooled contracts.
By avoiding shared pools and concentrating on isolation, Tscrow prioritizes containment and clarity over scale at all costs design.
Pull Payments
We use a "Pull Payment" pattern for withdrawals.
Push: Sending money directly can fail (out of gas, blocked receiver, malicious contract).
Pull: We update the balance inside the contract, and you call
withdraw()to take it out. This prevents "Denial of Service" attacks where a malicious user makes it impossible to refund them.
Last updated