CUBE BURSTSTUDIOS
coin-shop.zip
Details

Coin Shop (Exploit-Safe)

A server-checked shop: prices live on the server, coins are verified, tools are given safely. Includes the shop window.

Category
Code
File
coin-shop.zip
Size
3.0 KB
Downloads
0
Added
16 Oct 2026
Licence
Free to use, no credit needed (CC0)

#shop#store#remotefunction#security#tools#luau#roblox#script

⚑ Report this

A server-checked shop: prices live on the server, coins are verified, tools are given safely. Includes the shop window.

A simple, exploit-safe shop: the client asks to buy, the SERVER checks the price and the player's coins,
takes the coins and gives the tool. Exploiters can't give themselves items.

SETUP
1. Put this Script in ServerScriptService.
2. Make a Folder "ShopItems" in ServerStorage with your Tools inside (names must match CATALOG below).
3. Add the ShopClient LocalScript (in the download) to StarterGui for a ready-made shop window.
Coins come from leaderstats.Coins (works with the Leaderstats + Saving script).

The download also includes ShopClient.client.lua.

The main script is shown below with a Copy button, or grab the download with every file and a README.

ShopServer.server.lua
--[[
	Coin Shop (server-checked)  ·  by Cube Burst Studios  ·  CC0
	A simple, exploit-safe shop: the client asks to buy, the SERVER checks the price and the player's coins,
	takes the coins and gives the tool. Exploiters can't give themselves items.

	SETUP
	1. Put this Script in ServerScriptService.
	2. Make a Folder "ShopItems" in ServerStorage with your Tools inside (names must match CATALOG below).
	3. Add the ShopClient LocalScript (in the download) to StarterGui for a ready-made shop window.
	Coins come from leaderstats.Coins (works with the Leaderstats + Saving script).
]]

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")

-- the ONLY place prices live: the client is never trusted with them
local CATALOG = {
	["Speed Coil"] = 150,
	["Gravity Coil"] = 300,
	["Sword"] = 500,
}

local items = ServerStorage:WaitForChild("ShopItems")

local remote = Instance.new("RemoteFunction")
remote.Name = "BuyItem"
remote.Parent = ReplicatedStorage

local catalogValue = Instance.new("StringValue") -- lets the client show the list without hard-coding it
catalogValue.Name = "ShopCatalog"
catalogValue.Value = game:GetService("HttpService"):JSONEncode(CATALOG)
catalogValue.Parent = ReplicatedStorage

local lastBuy = {} -- [player] = os.clock(): stops spam-clicking

local function owns(player, name)
	return player.Backpack:FindFirstChild(name) ~= nil
		or (player.Character ~= nil and player.Character:FindFirstChild(name) ~= nil)
		or player.StarterGear:FindFirstChild(name) ~= nil
end

remote.OnServerInvoke = function(player, itemName)
	if type(itemName) ~= "string" then
		return false, "Bad request"
	end
	local price = CATALOG[itemName]
	local tool = items:FindFirstChild(itemName)
	if not price or not tool then
		return false, "That item isn't for sale"
	end
	if lastBuy[player] and os.clock() - lastBuy[player] < 0.5 then
		return false, "Slow down!"
	end
	lastBuy[player] = os.clock()
	if owns(player, itemName) then
		return false, "You already own this"
	end
	local stats = player:FindFirstChild("leaderstats")
	local coins = stats and stats:FindFirstChild("Coins")
	if not coins or coins.Value < price then
		return false, "Not enough coins"
	end
	coins.Value -= price
	tool:Clone().Parent = player.Backpack
	tool:Clone().Parent = player.StarterGear -- keep it after respawning
	return true, "Bought " .. itemName .. "!"
end

Players.PlayerRemoving:Connect(function(player)
	lastBuy[player] = nil
end)

MORE
CODE

View all ↗