Build a shop where players buy click multipliers, and the server verifies the price before anything changes.
Your clicker makes coins. Now it needs somewhere to spend them — an upgrades shop. Buying has one rule, and it's the security rule again: the server checks the bill. A player can say "I bought the multiplier," but only the server knows if they could afford it.
The upgrade level is real data, so it lives on the player's leaderstats — just like coins:
local multiplier = Instance.new("NumberValue")
multiplier.Name = "Multiplier"
multiplier.Value = 1
multiplier.Parent = stats -- your leaderstats folder
Add this in the same PlayerAdded block that makes Coins. Now every player has a Multiplier stat. The leaderboard will even show it, which is fun — but our real use is in the click math.
Where does the upgrade level live?
A purchase is a three-step conversation over a RemoteEvent:
FireServer("multiplier").Notice the client sends an intent ("multiplier"), never a price. The server owns the pricing.
In the purchase flow, the client sends an (like 'multiplier'), and the server supplies the
local purchaseEvent = ReplicatedStorage.BuyUpgrade
local UPGRADE_BASE_COST = 25
purchaseEvent.OnServerEvent:Connect(function(player, upgradeId)
if upgradeId ~= "multiplier" then
return -- don't recognize it, ignore it
end
local coins = player.leaderstats.Coins
local multiplier = player.leaderstats.Multiplier
local nextLevel = multiplier.Value + 1
local cost = UPGRADE_BASE_COST * nextLevel
if coins.Value >= cost then
coins.Value = coins.Value - cost
multiplier.Value = nextLevel
purchaseEvent:FireClient(player, coins.Value, multiplier.Value)
else
purchaseEvent:FireClient(player, coins.Value, multiplier.Value)
end
end)
Two checks before spending:
if upgradeId ~= "multiplier" — reject anything it doesn't understand.if coins.Value >= cost — the whole point. The client may claim a purchase; the server checks the wallet.The cost grows with level (cost = base * nextLevel) — the classic formula that makes early upgrades cheap and late ones expensive.
Before honoring a purchase, the server must check the player can afford it. Write the if-condition using their coins and the cost.
-- guard the purchase
Update the click handler on the server:
clickEvent.OnServerEvent:Connect(function(player)
local coins = player.leaderstats.Coins
local multiplier = player.leaderstats.Multiplier
if coins then
coins.Value = coins.Value + (1 * multiplier.Value)
clickEvent:FireClient(player, coins.Value)
end
end)
Clicks now earn 1 × multiplier. Buy a few levels and the clicker visibly accelerates. You have an economy.
The multiplier's power lives in the click math, not in the shop — which is why the shop just changes a number and the whole game changes with it.
A player with 10 coins tries to buy the 25-coin upgrade. What happens?
Next: the shop panel that puts this purchase in the player's hands.