Overview
PGC-1 is the ownership and access layer for a single game in Peridot. Responsibilities:- Store canonical
gameId - Store canonical publisher address
- Store canonical metadata URI
- Initialize canonical game state during deployment
- Mint non-transferable licenses
- Provide entitlement and access checks
- Manage authorized minters
- Preserve the strongest valid entitlement for each user
Data Structures
LicensePolicy
| Field | Type | Description |
|---|---|---|
| issuedAt | uint64 | Timestamp when license is minted |
| expiresAt | uint64 | Expiration timestamp |
Rules
expiresAt = 0means permanent licenseexpiresAt > nowmeans temporary valid licenseexpiresAt < nowmeans expired license
State
| Variable | Type | Description |
|---|---|---|
| gameId | string | Canonical game identifier |
| publisher | address | Canonical publisher address |
| metadataURI | string | Canonical metadata URI |
| minters | mapping(address => bool) | Authorized minters |
| licenses | mapping(address => LicensePolicy) | User license policy per account |
Functions
1. initialize
Initializes canonical game state.function initialize(gameId, publisher, metadataURI, initialMinter)
Params
| Name | Type | Description |
|---|---|---|
| gameId | string | Canonical game identifier |
| publisher | address | Canonical publisher address |
| metadataURI | string | Canonical metadata URI |
| initialMinter | address | Initial authorized minter |
Rules
- MUST only be callable once
gameIdMUST NOT be emptypublisherMUST NOT be zero addressmetadataURIMUST NOT be emptyinitialMinterMUST NOT be zero address
Behavior
- set canonical
gameId - set canonical
publisher - set canonical
metadataURI - authorize
initialMinter
Notes
- On EVM implementations this MAY be represented by constructor arguments
- On non-constructor environments this SHOULD be represented by an initialization function
2. mintLicense
Grants or upgrades a license for a user.function mintLicense(to, expiresAt)
Params
| Name | Type | Description |
|---|---|---|
| to | address | Receiver address |
| expiresAt | uint64 | License expiration timestamp |
Rules
- Only authorized minter
toMUST NOT be zero address- Permanent license MUST NOT be downgraded by a temporary license
- The strongest valid entitlement MUST be preserved
Behavior
If the user has no license:- create new license
- replace with incoming license
- upgrade to permanent
- keep permanent license
- incoming temporary license MUST NOT downgrade access
- extend or replace with later expiry
- keep current license
3. hasLicense
Returns whether a user owns a valid license for this game.function hasLicense(user)
Params
| Name | Type | Description |
|---|---|---|
| user | address | User address |
Returns
| Type | Description |
|---|---|
| bool | True if user owns a valid license |
Rules
- Expired licenses MUST return
false
4. canAccessGame
Returns whether a user can currently access this game.function canAccessGame(user)
Params
| Name | Type | Description |
|---|---|---|
| user | address | User address |
Returns
| Type | Description |
|---|---|
| bool | True if user has a valid non-expired license |
Rules
- Expired licenses MUST return
false
Notes
- This function is suitable as an entitlement check for launcher access, download authorization, and future DRM-like enforcement
- This function alone is NOT a complete DRM system
5. getLicensePolicy
Returns license policy data for a user.function getLicensePolicy(user)
Params
| Name | Type | Description |
|---|---|---|
| user | address | User address |
Returns
| Name | Type | Description |
|---|---|---|
| issuedAt | uint64 | Timestamp when license was minted |
| expiresAt | uint64 | Expiration timestamp |
6. setMinter
Updates minter authorization.function setMinter(account, isAuthorized)
Params
| Name | Type | Description |
|---|---|---|
| account | address | Minter address |
| isAuthorized | bool | Authorization status |
Rules
- Only publisher
accountMUST NOT be zero address- Event SHOULD be emitted
7. isMinter
Returns whether an account is an authorized minter.function isMinter(account)
Params
| Name | Type | Description |
|---|---|---|
| account | address | Account address |
Returns
| Type | Description |
|---|---|
| bool | Authorized minter status |
8. getPublisher
Returns canonical publisher address.function getPublisher()
Returns
| Type | Description |
|---|---|
| address | Publisher address |
9. getMetadataURI
Returns canonical metadata URI.function getMetadataURI()
Returns
| Type | Description |
|---|---|
| string | Metadata URI |
10. getGameId
Returns canonical game identifier.function getGameId()
Returns
| Type | Description |
|---|---|
| string | Game identifier |
11. setPublisher
Updates publisher address.function setPublisher(publisher)
Params
| Name | Type | Description |
|---|---|---|
| publisher | address | New publisher address |
Rules
- Only current publisher
publisherMUST NOT be zero address- Event SHOULD be emitted
Notes
- This function is optional if publisher is intended to be immutable in a specific implementation
12. setMetadataURI
Updates metadata URI.function setMetadataURI(metadataURI)
Params
| Name | Type | Description |
|---|---|---|
| metadataURI | string | New metadata URI |
Rules
- Only publisher
metadataURIMUST NOT be empty- Event SHOULD be emitted
Notes
- This function is optional if metadata is intended to be immutable in a specific implementation
Access Control
| Function | Access |
|---|---|
| initialize | Deployment only |
| mintLicense | Authorized Minter |
| hasLicense | Public |
| canAccessGame | Public |
| getLicensePolicy | Public |
| setMinter | Publisher |
| isMinter | Public |
| getPublisher | Public |
| getMetadataURI | Public |
| getGameId | Public |
| setPublisher | Publisher |
| setMetadataURI | Publisher |
Requirements
initialize()MUST set canonicalgameId,publisher, andmetadataURIinitialize()MUST only be executable oncegameIdMUST be stored in PGC-1publisherMUST be stored in PGC-1metadataURIMUST be stored in PGC-1mintLicense()MUST only be callable by authorized mintersgetPublisher()MUST return the canonical publisher for the gamegetMetadataURI()MUST return the canonical metadata URI for the gamegetGameId()MUST return the canonical game identifierhasLicense(user)MUST returnfalsefor expired licensescanAccessGame(user)MUST returnfalsefor expired licenses- Licenses MUST remain non-transferable
- Permanent licenses MUST NOT be downgraded by temporary licenses
- The strongest valid entitlement MUST be preserved for each user
Transferability
PGC-1 licenses are strictly non-transferable. Implementations MUST ensure:- licenses cannot be transferred between users
- any transfer attempt MUST fail
Subscription Compatibility
PGC-1 is intended for game-specific entitlement. Publisher-wide subscriptions, game bundles, or ecosystem-wide passes SHOULD be implemented in a separate access layer or contract. Such systems MAY grant additional access, but MUST NOT invalidate or downgrade a stronger permanent game license already held by the user.Notes
- PGC-1 is the source of truth for publisher and metadata
- Registry is the source of truth for game validity and moderation
- Game Store is the source of truth for pricing and purchase flow
- PGC-1 should remain minimal and ownership-focused
Chain Support
PGC-1 is designed to be chain-agnostic.EVM
- Built on top of ERC-1155
- Extended with license logic
- Transfer behavior MUST be disabled or restricted
Solana
- Implemented using Token-2022
- Extensions: NonTransferable, Metadata Pointer