Skip to main content

Overview

Game Store is the execution layer for purchasing games. Responsibilities:
  • Validate game from Registry
  • Process payment
  • Mint license via PGC-1
Game Store does NOT store metadata or governance logic.

Dependencies


Data Structures

PriceConfig


State


Functions

1. setPrice

Sets base price for a game. function setPrice(gameId, price, currency)

Params

Rules

  • Only publisher
  • msg.sender MUST match PGC1(contractAddress).getPublisher()
  • currency MUST be a valid supported payment token
  • Game MUST exist in Registry
  • price MAY be 0 for free games

2. setDiscount

Sets discount in basis points. function setDiscount(gameId, discountBps)

Params

Rules

  • Only publisher
  • msg.sender MUST match PGC1(contractAddress).getPublisher()
  • discountBps MUST be <= 10000

3. getFinalPrice

Returns final price after discount. function getFinalPrice(gameId): uint256

Returns

Logic

finalPrice = price - (price * discountBps / 10000)

4. buyGame

Executes purchase and mints license. function buyGame(gameId)

Flow

  1. Fetch game from Registry
  2. Validate status == approved
  3. Validate game.contractAddress exists
  4. Get PGC-1 contract
  5. Get publisher:
    • publisher = PGC1.getPublisher()
  6. Load PriceConfig
    • currency = prices[gameId].currency
  7. Calculate finalPrice
  8. Validate payment token and amount
  9. Prevent duplicate purchase by checking PGC1.canAccessGame(msg.sender)
  10. Calculate:
    • platformFee
    • publisherRevenue
  11. Receive payment
  12. Process split:
    • transfer(platformFee → treasury)
    • publisherBalances[publisher][currency] += publisherRevenue
  13. Call PGC1.mintLicense(msg.sender, 0)
  14. Revert whole transaction if mint fails

Internal Calls

  • const game = Registry.getGame(gameId)
  • const finalPrice = getFinalPrice(gameId)
  • PGC1(game.contractAddress).mintLicense(msg.sender, 0)
  • publisherBalances[publisher][currency] += publisherRevenue

Rules

  • If finalPrice == 0, payment transfer MAY be skipped
  • Game MUST have a valid PriceConfig before purchase (Including Free Game)
  • Purchase, accounting update, and minting MUST be executed atomically
  • Mint MUST only happen AFTER payment is recorded
  • If mint fails → transaction MUST revert
  • Double purchase MUST be prevented if the buyer already owns a valid license for the same game.

5. setPlatformFee

Updates platform fee. function setPlatformFee(feeBps)

Params

Rules

  • Only governance
  • feeBps MUST be <= 10000

6. withdraw

Withdraw publisher earnings per token. function withdraw(token)

Params

Rules

  • Only publisher
  • Balance MUST be > 0
  • Withdrawal MUST revert if transfer fails

Behavior

  • amount = publisherBalances[msg.sender][token]
  • publisherBalances[msg.sender][token] = 0
  • transfer(token → msg.sender)

7. setGovernance

Updates governance address. function setGovernance(governance)

Params

Rules

  • Only current governance
  • Governance MUST NOT be zero address
  • Event SHOULD be emitted

8. setTreasury

Updates treasury receiver address. function setTreasury(treasury)

Params

Rules

  • Only governance
  • Treasury MUST NOT be zero address
  • Event SHOULD be emitted

9. getPriceConfig

Returns pricing configuration for a game. function getPriceConfig(gameId)

Params

Returns

10. getPublisherBalance

Returns withdrawable publisher balance for a token. function getPublisherBalance(publisher, token)

Params

Returns

11. getPlatformFee

Returns current platform fee in basis points. function getPlatformFee()

Returns

12. getTreasury

Returns treasury receiver address. function getTreasury()

Returns

13. getGovernance

Returns governance address. function getGovernance()

Returns

14. getRegistry

Returns registry contract address. function getRegistry()

Returns


Payment Flow

Hybrid (Push + Escrow) Payments are split during purchase:
  • Platform fee → sent directly to treasury
  • Publisher revenue → stored in contract (escrow)

Flow

  1. User pays finalPrice
  2. Contract calculates:
    • platformFee
    • publisherRevenue
  3. Execute transfers:
    • send platform fee to treasury
    • publisherBalances[publisher][currency] += publisherRevenue
  4. Mint license

Withdraw

  • Publisher MUST call withdraw(token) to claim revenue
  • Treasury does NOT use withdraw, because platform fee is transferred directly during purchase

Revenue Split


Access Control


Requirements

  • Game MUST be approved in Registry
  • Registry MUST return a valid contractAddress
  • Registry MUST return game status
  • Store MUST be authorized minter in PGC-1
  • PGC-1 MUST implement getPublisher()
  • PGC-1 MUST implement canAccessGame(user)
  • PGC-1 MUST implement mintLicense(to, expiresAt)
  • Payment MUST succeed before mint

Notes

  • Price is dynamic (not stored in Registry)
  • Supports future extensions:
    • subscription
    • bundle
    • regional pricing