GridCoreGridCore
Smart Contract

Program Reference

Program ID, all 8 instructions, PDA seeds, account layouts, and fee constants for the GridCore Anchor program.

Program Details

On-chain identity and network.

Deployment Info
Program IDAWNUk1NmmNkaQvjFyrmKcS7Y13mD2PjWVWiiV4tRwrKW
NetworkSolana Devnet (mainnet migration pending)
FrameworkAnchor v0.30
LanguageRust
Module namegridcore
TreasuryHardcoded in the program binary — no on-chain config account
Upgradeable — deployer holds authority

The program is upgradeable. The deployer holds the upgrade authority. A future audit will precede any upgrade authority burn.

No admin-only instructions

There is no admin instruction or GlobalConfig account. The treasury wallet address is hardcoded in the binary at compile time. No instruction changes program logic after deployment.

All state is on-chain

GridState and TileState are the canonical source of truth. No off-chain database is authoritative. The frontend reads directly from program accounts via getProgramAccounts.

Instructions

All 8 callable instructions and their purpose.

Discriminators use the seed pattern "global:instruction_name" — the first 8 bytes of SHA-256 of that string.

launch_coin(name, symbol, uri, starting_price)

Creates a GridState PDA for a given SPL mint. The caller becomes the grid creator permanently and receives 0.4% of every future buyout. The grid is immediately live and tiles are claimable.

acquire_tile(seat_index)

Claims an empty tile OR buys out an existing holder. First claim: pays starting_price, tile auto-lists at 1.2×, no seller payout. Buyout: pays listed price; seller receives 98%; 2% fee split (1% pool, 0.4% creator, 0.6% treasury). A 20-minute protection window starts for the new holder.

set_multiplier(new_multiplier)

Changes the resale multiplier to 120 (1.2×), 150 (1.5×), or 200 (2.0×). Updates listed price = acquisition_price × multiplier / 100. First change is immediate; subsequent changes have a 24-hour cooldown.

set_price(new_price)

Sets a custom absolute listed price. Floor: new_price ≥ acquisition_price × current_multiplier / 100. No cooldown — can be called any time.

abandon_tile()

Holder voluntarily gives up their tile. Holder pays 2% of their current listed price as an exit fee (same 1%/0.4%/0.6% split). No SOL is refunded. Tile resets to unowned state at the grid's starting_price. Requires 20-minute protection window to have elapsed.

claim_reward()

Transfers accumulated rewards from vault to holder. Amount = (accumulator − reward_debt) / PRECISION. Rewards are equal per tile — one share per tile regardless of price.

inject_rewards(amount)

Anyone can inject SOL directly into the grid's reward accumulator. If no tiles are held yet, SOL parks in pending_seed and is flushed on first tile acquisition.

withdraw_seed()

Creator-only. Reclaims any SOL injected via inject_rewards before any tiles were claimed. Once the first tile is acquired, pending_seed is permanently flushed to the accumulator.

PDA Seeds

Deterministic account addresses for all program accounts.

All accounts are Program Derived Addresses. The frontend derives these off-chain before submitting transactions. Seeds must match the program exactly.

PDA Seed Table
GridState["grid", mint_pubkey]
TileState["tile", mint_pubkey, seat_index_byte]
Vault["vault", mint_pubkey]
// TypeScript — derive TileState for seat index 7 const [tileState] = PublicKey.findProgramAddressSync( [Buffer.from("tile"), mint.toBuffer(), Buffer.from([7])], PROGRAM_ID ) // Vault for a given mint const [vault] = PublicKey.findProgramAddressSync( [Buffer.from("vault"), mint.toBuffer()], PROGRAM_ID )
⚠ seat_index is a single byte (u8), valid range 0–99. Passing a value outside that range succeeds at the PDA derivation level but will be rejected by the program at runtime.

Fee Constants

All hardcoded rates in the program.

Program Constants (lib.rs)
POOL_FEE_BPS100 → 1% of tile price → equal-per-tile reward accumulator
CREATOR_FEE_BPS40 → 0.4% of tile price → grid creator wallet
TREASURY_FEE_BPS60 → 0.6% of tile price → treasury wallet (hardcoded)
TOTAL_FEE_BPS200 → 2% total fee (taken FROM listed price)
DEFAULT_MULTIPLIER120 → 1.2× auto-resale price after acquisition
PROTECTION_SECS1200 → 20-minute protection window after acquisition
MULTIPLIER_COOLDOWN86400 → 24 hours between set_multiplier calls
PRECISION1,000,000,000,000 → 1e12 fixed-point for accumulator
ℹ️ The 2% fee is taken from the listed price — not added on top. A buyer paying 1.00 SOL causes the seller to receive 0.98 SOL. The buyer never pays more than the listed price.
GridState Layout (375 bytes total = 8 discriminator + 367 body)
mintPubkey — 32 bytes
creatorPubkey — 32 bytes
starting_priceu64 — 8 bytes
tiles_heldu64 — 8 bytes (occupied tile count; accumulator divisor)
nameString max 32 — 36 bytes
symbolString max 10 — 14 bytes
uriString max 200 — 204 bytes
total_feesu64 — 8 bytes (cumulative fees processed)
reward_accumulatoru128 — 16 bytes
pending_seedu64 — 8 bytes (injected SOL before first tile)
bumpu8 — 1 byte
TileState Layout (123 bytes total = 8 discriminator + 115 body)
mintPubkey — 32 bytes
holderPubkey — 32 bytes (default pubkey = empty tile)
seat_indexu8 — 1 byte
priceu64 — 8 bytes (current listed price)
acquisition_priceu64 — 8 bytes (what holder paid; floor reference for set_price)
buyout_multiplieru8 — 1 byte (120, 150, or 200)
acquired_ati64 — 8 bytes (unix timestamp; protection window start)
last_multiplier_changei64 — 8 bytes (unix timestamp; 24h cooldown reference)
reward_debtu128 — 16 bytes
bumpu8 — 1 byte