Roblox Trading with Anti-Fraud Escrow and Atomic Transactions
Generate the professional core of a Roblox trading system with real server-side security. The prompt guides the AI to create a server-authoritative Luau Script capable of controlling invites, trade sessions, item and currency offers, independent confirmations, cancellations, and automatic expiration.
The system includes protections against duplication, offer changes after confirmation, RemoteEvent spam, nonexistent or non-tradable items, insufficient balance, concurrent sessions, and client-side tampering. It is suited for RPGs, simulators, collection games, tycoons, and experiences with persistent inventory.
It also requests an adapter layer to connect the code to the existing structure of your game, allowing you to provide folder names, RemoteEvents, inventory values, profile modules, and custom trading rules before generating the script ready to use in Roblox Studio.
Act as a senior Roblox Luau developer, specialized in server-authoritative multiplayer systems, persistent inventory, DataStore/ProfileService, and exploit prevention. Generate a central player trading system with anti-fraud validation, implemented primarily in a single **Script** on the server. The main script should be placed in **ServerScriptService**, for example with the name `TradingServer`. It must safely create or locate the necessary RemoteEvents in `ReplicatedStorage/Remotes` (without duplicating them if they already exist) and expose a clear communication contract for the client UI. Do not generate the full graphical interface; focus on the secure server core and, at the end, document which RemoteEvents and arguments a UI LocalScript should fire. If my context indicates RemoteEvents already exist, reuse the exact names and paths provided. Before generating the code, consider and incorporate this context from my game. If any field is blank or nonexistent, adopt a safe default implementation, state the assumption before the code, and concentrate the adaptation points in a `CONFIG` and/or `InventoryAdapter` section at the start of the Script: - Paths and object names in Explorer: [PASTE HERE] - RemoteEvents/RemoteFunctions already existing and their arguments: [PASTE HERE] - Inventory structure (Folder/Value, table in ModuleScript, ProfileService, DataStore, etc.): [PASTE HERE] - How items are identified, maximum stack quantity, and item attributes: [PASTE HERE] - Rules for tradable items, bound items, rarities, and currency: [PASTE HERE] - Player currency name and location, if any: [PASTE HERE] - Maximum distance to start a trade and other UX rules: [PASTE HERE] - Save/persistence system already used by the game: [PASTE HERE] Implement an explicit, server-validated state machine, for example: `Idle`, `InviteSent`, `Trading`, `Confirming`, `Committing`, `Completed`, `Cancelled`. Each session must have a unique ID, fixed participants, timestamps, expiration deadline, and offer version/revision control. A player cannot participate in two simultaneous sessions. Invites must expire, be able to be declined, and be invalidated if the player leaves the server. Any disconnection must cancel the session and release locks safely. The server must be the sole authority for inventory, currency, item ownership, item quantity, rarity, eligibility, and trade completion. Never accept from the client price, balance, damage, item ID, quantity, or confirmation state as absolute truth. For each remote call, rigorously validate: Luau types with `typeof`, the sending player, session existence, participation in the session, allowed state, offer size limit, valid IDs, positive integer quantities, stack limits, current possession of the item, unreserved availability, and tradable-item rules. Apply rate limiting per player and per action, ignore/reject excessive requests, and emit server warnings for suspicious attempts. Implement logical escrow/reservation: when adding an item or currency to the offer, mark that quantity as reserved to prevent use, sale, equipping, or concurrent offering while the session exists. Do not permanently remove assets when building the offer, but revalidate everything at commit time. Any modification to item, quantity, or currency must increment the offer revision and reset both players' confirmations. Confirmation is only valid for the current revision and must require independent confirmation from both participants. When both confirm, execute an atomic transaction on the server: lock the session against reentry, fully revalidate both inventories and balances, apply transfers in a safe order, handle failures with rollback, and only then finalize as completed. Avoid duplication and item loss. If the persistent inventory uses ProfileService/DataStore, do not perform unsafe DataStore calls on every click; integrate with the loaded profile and clearly describe where the adapter should perform persistence. Do not use `loadstring`, do not trust client-editable attributes, and do not allow RemoteEvents to accept arbitrary tables without deep sanitization. Deliver first a brief list of assumptions and the architecture. Then deliver the complete, functional, commented, ready-to-paste Luau code, exclusively inside a markdown block ` ```lua `. The code must include remote creation/location, configuration, useful types when applicable, `PlayerAdded`/`PlayerRemoving` connections, session cleanup, automatic expiration, administrative logs, and well-separated functions. Do not deliver pseudocode, incomplete snippets, `...`, or hidden dependencies. If you need an inventory adapter, implement a standard functional version and leave clear markers for replacement with my structure. After the code block, provide: (1) a table of the RemoteEvents and arguments expected by the client UI; (2) objective steps to connect my real inventory to the `InventoryAdapter`; (3) detailed instructions for testing in Roblox Studio using `Test > Start` with two players, including success, cancellation, disconnection, spam, offer change after confirming, insufficient balance, invalid item, and double-trade attempt scenarios; and (4) a short list of limitations or points that require adaptation to my persistence system.