Gems

what is Gems

Gems is a launchpad for mineable tokens on Solana. A token here has a fixed supply that is released round by round, and mining is the only way new units reach anyone.

  1. 01

    launch

    Choose the name, ticker and metadata. Supply and mining rules are fixed at launch. No creator or token admin can change them later.

  2. 02

    stake

    Deposit token units into the excavation. That deposit is your weight for the round. It stays yours, and you can withdraw it once the round it weighted has settled.

  3. 03

    dig

    Your browser builds a proof each round and submits it. Everyone who submits splits that round's emission in proportion to what they staked, not by who solved it first.

  4. 04

    claim

    Rewards accrue as each round closes. Claim them when you want, without stopping mining.

Mining pays Solana transaction fees every round. This site is showing demo data. Market and mining values are not live.

launch

Gems: fixed-supply mineable tokens on Solana

A launched token's supply, emission schedule, difficulty and round length are set in one transaction and cannot be changed afterwards by anyone, including its creator and including the people who wrote this program. Everything below is a consequence of that constraint, stated as a numbered clause with the file that has to be read to check it.

Revision 1, August 2026 · 10 parts · 47 clauses

contents
  1. 1position
  2. 2immutability
  3. 3rounds and emission
  4. 4weight and settlement
  5. 5proof of work
  6. 6multi-tenancy
  7. 7platform authority and fees
  8. 8clients
  9. 9status
  10. 10provenance
part 1

position

What Gems issues, what it refuses to issue, and the one property everything else here exists to protect.

1.1

Gems issues tokens whose rules cannot be edited

A token launched through Gems fixes its supply, its emission schedule, its round length, its difficulty and its creator allocation in the launch transaction. There is no update instruction, no stored admin key and no setter that can widen a guardrail afterwards. The launched token has no administrator at all.

This is the product's only real claim, and it is a structural claim rather than a promise. The program contains no code path that could change a launched token's parameters, so keeping the claim true does not depend on anyone choosing to behave.

in plain languageprograms/Gems/src/instructions/launch.rs · no admin exists after this returnsAGENTS.md · hard forbids

1.2

Proof of work here is a distribution mechanism, not a security mechanism

Solana provides consensus. The proof of work in Gems does not secure a chain and does not order transactions. It exists to make new supply cost something to obtain, and to make that cost payable by anyone with a browser rather than only by whoever runs the fastest hardware.

That framing is what allows fixed difficulty. A chain that used proof of work for security would have to retarget; a distribution mechanism does not.

in plain language

1.3

A share of a round is proportional, not competitive

Rounds do not have a winner. Every wallet that submits one accepted proof during a round is credited weight, and when the round closes its emission is divided across all of that weight in proportion.

Solving faster than another miner earns nothing extra. Solving at all is the entry condition; the size of the share comes from staked units, which is why a browser can compete with a datacenter for the same round.

in plain languageprograms/Gems/src/round.rs · settle

1.4

Gems does not create liquidity, price, or a market

The current build creates a mint, a fixed supply, an emission vault and a stake vault. It does not open a liquidity pool, lock one, or route a trade. A launched token has no price until someone independently creates a market for it.

A permissionless pool created after the mint is published can be front-run: on mainnet, another party was able to initialize the canonical mint pair first, at an arbitrary price. The prototype that did this was removed rather than shipped behind a preflight check that does not close the race.

STATE.md · rejected or deferred choices

1.5

Random payouts are excluded permanently

There are no jackpots, lotteries, prize draws or random bonuses, and none will be added. Consideration, chance and prize together are the gambling-law test, and a launchpad that meets that test in one jurisdiction meets it for every user in that jurisdiction.

This is recorded as a standing prohibition in the repository rather than a product preference, so that it survives a change of contributor.

AGENTS.md · hard forbids

part 2

immutability

The guardrails are checked once, in the launch instruction, and there is no later opportunity to check them again.

2.1

No instruction accepts a token creator as a signer

LodeConfig records a creator public key. It is attribution and nothing else. No instruction in the program reads that field to authorize an action, and no account context requires it to sign.

A creator therefore has exactly the same authority over a launched token as any other wallet, which is none.

programs/Gems/src/state.rs · LodeConfig::creator

2.2

Launch parameters are validated against fixed ranges, then frozen

The launch instruction rejects any parameter outside the ranges below. Because no admin exists afterwards, these bounds are the only protection against a launcher shipping absurd parameters, and they are compiled into the program rather than stored in a mutable account.

round length
30 to 3,600 seconds
halving interval
1,440 to 5,256,000 rounds
creator allocation
0 to 1,000 bps, and greater than zero base units
decimals
exactly 6
equihash
exactly n=96, k=5
base weight
exactly 0
name / symbol / uri
32 / 10 / 200 bytes
difficulty target
non-zero

in plain languageprograms/Gems/src/state.rs · guardrail constantsprograms/Gems/src/instructions/launch.rs · handler preamble

2.3

The creator allocation is capped at 10% and is displayed at full size

MAX_PREMINE_BPS is 1,000 basis points. The allocation is minted directly to the creator at launch, recorded on the config, emitted in the launch event, and required by the frontend specification to appear on the token page at the same size as every other fact.

Raising that ceiling requires an explicit recorded decision, not a code change alone.

MAX_PREMINE_BPS
1000

programs/Gems/src/state.rs · MAX_PREMINE_BPS

2.4

The supply cap is structural at the token-program level

Launch mints the entire supply in one transaction, splits it between the creator allocation and the emission vault, and then revokes the mint authority. No freeze authority is set.

After that transaction, no further units of the token can be created by anyone, including the Gems program itself. The cap does not depend on Gems's own arithmetic being correct.

programs/Gems/src/instructions/launch.rs · mint_to then set_authority

2.5

Metadata is immutable and is funded by the creator

A launched token carries a Metaplex fungible metadata account created as immutable. The launcher supplies a permanent metadata URI on Arweave, Irys or IPFS, which the browser fetches and checks before building the transaction: the document must carry the exact on-chain name and symbol and a content-addressed image.

Gems holds no storage credential and operates no upload proxy, so uploading and paying for those permanent files is a prerequisite the creator completes elsewhere. A server-funded upload route was removed rather than left disabled, because a paid quota that anyone can call can be drained by callers who never launch.

in plain languageweb/src/features/launch/metadata.ts · pre-signature validationSTATE.md · frontend and clients

2.6

A version 2 config cannot be reinterpreted from legacy bytes

The stake model carries an account version, stored in the first byte of the region an earlier layout reserved. A legacy account therefore decodes as version zero, and every version 2 writer refuses it rather than reading old balance bytes as backed stake.

Legacy launch and mine are disabled. Legacy claim, crank and close remain available so that anyone holding a position under the earlier model can still exit it.

STAKE_MODEL_VERSION
2

programs/Gems/src/state.rs · uses_stake_model

part 3

rounds and emission

Emission is a pure function of the round index, and the round index advances on the wall clock.

3.1

A round is a wall-clock interval, not a race to a solution

A round closes once round_seconds have elapsed since it opened. Hashrate does not shorten it and idleness does not extend it. The next round's boundary is advanced from the previous scheduled boundary rather than reset to the current time, so a token nobody has cranked for an hour catches up one round at a time instead of losing the schedule.

in plain languageprograms/Gems/src/state.rs · round_elapsed, next_round_open_ts

3.2

Difficulty never retargets

Because the cadence is set by the clock, more hashrate cannot make rounds arrive faster, and there is nothing for a retarget to correct. The difficulty target is chosen at launch and is then fixed for the life of the token.

Difficulty here is a liveness bar rather than a race. It answers the question of whether a participant did real work this round; it does not decide who wins one. Equium, the project Gems derives from, retargets because its rounds end on a solution. That logic was deleted deliberately.

in plain languageprograms/Gems/src/state.rs · module documentation

3.3

Emission halves on a fixed interval and is never stored

The reward for a round is computed as the initial reward right-shifted by the number of completed halving intervals, and it is computed on demand rather than cached. A stored current reward mutated at each boundary would be a second source of truth that can drift if a boundary is ever missed.

After 64 halvings the reward is zero.

halvings
(round_index - 1) / halving_rounds
reward
initial_round_reward >> halvings

in plain languageprograms/Gems/src/state.rs · LodeConfig::reward_at

3.4

A schedule that cannot release the full allocation is rejected at launch

Launch sums all 64 integer right-shift tranches of the proposed schedule and fails if the resulting lifetime emission is smaller than the Gems allocation. A token whose arithmetic would strand supply in the vault forever cannot be created.

programs/Gems/src/state.rs · scheduled_lifetime_emission

3.5

A round's budget is frozen when the round closes, and capped by the vault

The budget recorded for a closing round is computed against that round's own index, so a halving landing on the boundary cannot retroactively shrink work miners have already done. It is also clamped to the vault's remaining balance, so settlement can never promise more than exists.

Reserving the budget at close means cumulative_mined tracks what is owed rather than what has been transferred, which is what keeps the remaining figure honest for the next round's cap.

programs/Gems/src/round.rs · maybe_close_round

3.6

One crank call advances exactly one round

The crank is permissionless and idempotent: calling it when nothing is due returns without touching state. It deliberately does not loop to catch up an idle token, because such a loop is bounded only by elapsed time and would exhaust the compute budget. The instruction is cheap enough to call repeatedly instead.

Mining requires a live round. A miner cannot roll the round forward inside their own submission, which would either verify against a challenge they did not solve or let them mine a historical round.

programs/Gems/src/round.rs · maybe_close_roundprograms/Gems/src/instructions/mine.rs · RoundElapsed guard

3.7

An empty round lapses

If no wallet submitted during a round, its budget is not reserved and not carried forward. The round is recorded as an empty tombstone and the emission for that interval is simply never released; the supply stays in the vault and the schedule continues from the next index.

programs/Gems/src/round.rs · empty_rounds

part 4

weight and settlement

Weight is custody. A token unit can back at most one wallet's share of at most one round at a time.

4.1

Weight is program-custodied stake, and base weight is zero

A miner's weight for a round is exactly the number of the token's own units they have deposited into that token's stake vault and which are active. There is no per-wallet base weight and no wallet-balance snapshot.

Both alternatives were tried and rejected. A positive base weight lets one holder multiply their weight by splitting across free identities. A balance snapshot counts transferable units, which can be moved through a series of pre-warmed wallets and counted more than once.

DEFAULT_BASE_WEIGHT
0

in plain languageprograms/Gems/src/instructions/mine.rs · weight = miner.active_stakeSTATE.md · rejected or deferred choices

4.2

A deposit activates in the following round

Deposited units land as pending stake with an activation round of the current index plus one, and are promoted to active stake only once that round exists. The units are in program custody the whole time.

The delay closes the atomic path in which a wallet borrows units, deposits them, mines, withdraws and repays inside a single transaction.

in plain languageprograms/Gems/src/instructions/deposit_stake.rs

4.3

Stake that weighted an unsettled round cannot be withdrawn

Withdrawal requires the miner to carry no unsettled round weight. If the wallet submitted a proof in a round that has not yet been settled, the whole position is locked until it settles, not just the portion that was counted.

The simple whole-position rule is deliberate. A partial rule would let principal move to a second wallet while it is still present in the first wallet's numerator for a round that has not paid out.

in plain languageprograms/Gems/src/instructions/withdraw_stake.rs · StakeLocked

4.4

Settlement is pro-rata and truncates toward the vault

A miner's share of a closed round is the round's budget multiplied by their credited weight, divided by the round's total weight, computed through a 128-bit intermediate and truncated to an integer.

Truncation always favours the vault: the sum of integer-divided shares can never exceed the budget, so a round cannot pay out more than it reserved. The remainder is not redistributed and not rounded up. Doing either would create a path that overdraws the vault.

share
budget * weight / total_weight

in plain languageprograms/Gems/src/round.rs · settle

4.5

Settlement history is a bounded ring of 32 rounds

A round's total weight is only known once it closes, so a miner settles their share on their next action rather than at the moment of submission. The closed rounds available to settle against are held in a fixed 32-slot ring inside the config account.

A slot resolves only when the round number stored in it equals the round being asked for, so a round that has been lapped stops resolving instead of returning a newer round's numbers. Round zero never enters the ring, because a zeroed slot would otherwise read as a real entry.

At a 60-second cadence the ring covers roughly 32 minutes. A miner who acts every round always settles; one who walks away for longer forfeits the unsettled tail. The alternative, one account per round, costs rent per token that grows without bound.

ROUND_RING
32

programs/Gems/src/state.rs · ring_slot, ROUND_RING

4.6

Direct transfers into a stake vault are uncredited donations

Only a deposit instruction increases total_staked or any miner's credited principal. Tokens sent directly to the stake vault address raise the vault balance without raising anyone's claim on it.

The accounting invariant this preserves is that the sum of credited stake equals total_staked, which is less than or equal to the vault's actual balance. Liabilities stay bounded by assets in every case, including the donation case.

programs/Gems/src/instructions/deposit_stake.rs

4.7

Claiming is separate from mining and from withdrawing

Mining accrues weight and never moves tokens. Claim moves settled rewards from the emission vault. Withdraw returns principal from the stake vault. The two vaults are distinct accounts, so a claim can never consume withdrawable principal.

Claim also cranks and settles on the way through, so a miner who has stopped mining can still collect the last round they worked without waiting for anyone else to act.

programs/Gems/src/instructions/claim.rs

part 5

proof of work

Equihash (96,5), with the token mint and the miner's key bound into the input block.

5.1

The input block binds the mint and the miner

The Equihash input block is 113 bytes: a 9-byte personalization string, the mint, the current challenge, the miner's public key, and the round index as a little-endian 64-bit integer.

Binding the miner's key defeats front-running, because a copyist would have to re-sign under their own key, which produces a different input block and invalidates the solution. Binding the mint defeats cross-token replay: many tokens share one program, and without the mint a solution valid for one token would be valid for another whenever their challenge and round index coincided.

This construction exists in exactly one place and must stay byte-identical on-chain, in the CLI and in the browser miner. A test asserts that changing the mint changes the input block.

I
PERSONALIZATION || mint || challenge || miner || round_index_le
PERSONALIZATION
"Lode-v1.0", 9 bytes
I_LEN
113 bytes

in plain languagecrates/equihash-core/src/challenge.rs · build_inputprograms/Gems/src/pow.rsclients/web-miner/wasm/src/lib.rs

5.2

The challenge chain is unpredictable before a round opens

Each new challenge is the SHA-256 of the mint, the previous challenge and a slot hash read from the SlotHashes sysvar at the slot the round opens. Because that slot hash does not exist until the round opens, nonces cannot be precomputed for a future round.

A token's genesis challenge is derived from the mint and the launch slot hash, with no launcher-supplied input, so a genesis challenge cannot be chosen to collide with a live token's current challenge.

next
sha256(mint || prev_challenge || open_slot_hash)
genesis
sha256("lode-genesis" || mint || launch_slot_hash)

crates/equihash-core/src/challenge.rs

5.3

One accepted solution per wallet per round

A wallet that has already been credited weight in the open round is rejected if it submits again. Without this rule a miner could resubmit repeatedly to inflate their weight, which is the dynamic that turns a mining program into a transaction-spam auction.

Combined with weight being staked units, repeated solving and wallet splitting both change nothing: splitting a position across two wallets produces two submissions whose weights sum to the original.

programs/Gems/src/instructions/mine.rs · AlreadySubmitted

5.4

A submission with zero active stake is rejected

Verification of the proof happens first, but weight is read afterwards, and a miner whose active stake is zero cannot submit. Solving alone does not enter a wallet into a round.

programs/Gems/src/instructions/mine.rs · StakeRequired

5.5

Solving runs in the browser as WebAssembly

The solver is compiled from the same Rust crate the program verifies with, and runs in a worker so the interface stays responsive. Missing a round is normal and is reported as a missed round rather than as an error.

Verification of one submission was measured at 219,715 compute units on the version 2 instruction. Clients request a 300,000-unit limit.

measured mine_v2
219,715 CU

in plain languageclients/web-miner/wasm/src/lib.rsweb/src/features/mine/solver.worker.ts

part 6

multi-tenancy

One deployed program hosts an unbounded number of independent tokens, isolated by mint-seeded accounts.

6.1

Every account except the platform is seeded by the mint

A token's configuration, emission vault, stake vault and per-wallet miner accounts are all program-derived addresses that include the mint in their seeds. Two tokens can therefore never share state, and an account belonging to one token cannot be passed into an instruction operating on another.

config
["lode-config", mint]
emission vault
["lode-vault", mint]
stake vault
["lode-stake-vault", mint]
miner
["lode-miner", mint, authority]
platform
["lode-platform"], singleton

in plain languageprograms/Gems/src/state.rs · PDA seeds

6.2

Cross-token replay is closed at both ends

The mint is inside the input block, so a proof produced for one token hashes to a different value under another. The mint is also inside the challenge derivation, so two tokens whose challenge chains ever coincided diverge at the next round instead of remaining in lockstep.

Isolation and replay rejection are both covered by the compiled-program integration suite rather than by unit tests alone.

crates/equihash-core/src/challenge.rstests/ · tenant isolation, cross-token replay

6.3

Round history costs no additional accounts

Holding settlement history inside the config's fixed ring, rather than as one account per round, means a token's history costs no rent beyond the config account itself, at any age and at any number of miners.

The cost of that choice is the bounded window described in the settlement clause, and it is the intended trade.

programs/Gems/src/state.rs · ROUND_RING rationale

part 7

platform authority and fees

The only account carrying live authority anywhere in the program is a singleton that cannot touch a launched token's economics.

7.1

The platform singleton holds the only live authority

One platform account stores an authority key, a fee recipient and two flat lamport fees. It can be initialized only by the deployed program's current upgrade authority, and it may assign a separate operational authority distinct from that upgrade key.

Nothing on this account can alter a launched token's supply, emission, difficulty, round length or creator allocation. Its reach is limited to fees and to the fee recipient.

programs/Gems/src/state.rs · Platformprograms/Gems/src/instructions/init_platform.rs

7.2

Every fee is bounded by a maximum the user signs

Launch and mine both take a maximum fee parameter and fail if the live platform fee exceeds it. A fee raised between the moment a transaction is built and the moment it lands causes that transaction to fail rather than to charge more than the signer agreed to.

The mine fee is charged per instruction rather than per transaction, so packing many miners into one transaction saves nothing.

programs/Gems/src/instructions/mine.rs · PlatformFeeExceedsMaximum

7.3

Fee values for mainnet are not yet set

The launch and mine fee values, and the choice of a distinct operational platform authority key, are open decisions. Until they are chosen and initialized, no figure for them appears anywhere on this site.

TASKS.md · release blockers

part 8

clients

The web app reads chain state directly and never asks a wallet to sign bytes it has not itself simulated.

8.1

Chain state is authoritative and there is no indexer

The app reads Gems, SPL Token and Metaplex accounts directly over RPC and refreshes them from program subscriptions. No database, no indexing service and no backend cache sits between the program and what the page displays.

Where a value is genuinely unknown, the interface renders it as unknown rather than as a zero or a dash that could be mistaken for a real figure.

web/src/lib/solana/reads.ts

8.2

The browser signs exactly the bytes it simulated

The client compiles and simulates a transaction, then requires the wallet to return those exact message bytes under the same blockhash lifetime. It persists the signature, the lifetime and a typed receipt before broadcasting.

An unresolved transaction survives a page reload: the client searches status history through expiry and acknowledges the action only after authoritative state has been re-read. A browser-wide exclusive lock prevents two tabs from signing at once.

web/src/features/transactions/pipeline.tsweb/src/features/transactions/recovery.ts

8.3

Wallets that cannot return a signed transaction are not offered

Wallet discovery requires the solana:signTransaction feature. Sign-and-send-only wallets are hidden rather than shown and then failed, because the executor cannot verify what such a wallet actually broadcast.

Gems never generates, imports, exports or stores a private key in the browser.

web/src/lib/solana/wallet-capabilities.ts

8.4

A wallet is an authorization key, not an identity

Nothing in the reward model treats one wallet as one person. There is no per-wallet bonus, no proof of personhood and no attempt to detect a wallet split, because every such attempt is defeated by generating another keypair.

The model is built so that splitting is neutral rather than penalized.

part 9

status

What has been verified, what has not, and what is not built. Read this part before assuming anything above it is live.

9.1

Every excavation on this site runs on mainnet with a Raydium pool

Gems runs on mainnet, and every launched token gets a Raydium pool. Tokens launched here are mainnet tokens with a Raydium pool from day one.

The program address currently live on mainnet hosts an earlier build. The reviewed version 2 program has not yet been deployed to it.

program id
AB6LW5ccieBFVqXVLiLFTuQ84tAbPuefXSNHJJuNBmJg
cluster
mainnet

in plain languageSTATE.md · cluster state

9.2

Local verification that has been run

The workspace host tests, the compiled-program integration suite and the web checks all pass on the current local source. The integration suite covers two tokens, two wallets and three weighted rounds with exact balances, plus replay isolation, cycling prevention, wallet splitting, donations, ring eviction, legacy gates, metadata and fee ceilings.

An independent program review and an independent review of the web transaction path each found no remaining high-severity findings in their reviewed scopes.

host tests
equihash 12, program 17, wasm 1
cli tests
7
integration
24 against the compiled program
web tests
23, plus lint, typecheck and build
program sha-256
426c36de596e94dc50f27e30be9337d111a3f531888c1d4b1fde3171852cbd34

in plain languageSTATE.md · verification

9.3

What is not proven

These are component and local results. The exact current artifact has not completed an end-to-end run against a deployed program, and until it has, nothing on this site should be read as evidence that the deployed flow works.

Specifically unproven: the deployed acceptance path across two tokens and two wallets; the reproducible container build, which is staged but has so far recorded a local build mode; and the real wallet browser path against the reviewed artifact. No independent security review has been commissioned.

in plain languageTASKS.md · release blockers

9.4

Not built

The following are named because people ask about them, and each one is absent from the current build rather than planned for a date. No timeline is attached to any of them.

Liquidity creation or locking, which is deferred until an atomic launch-and-pool transaction fits or a reserved-pool design is reviewed against live protocol state. Mainnet deployment, which requires the upgrade authority to sit behind an independently controlled multisig with a nonzero timelock and an independent program review first. Aggregator routing and token verification, which are outcomes decided by third parties and will not be promised here.

Also absent from version 1 by decision: charts, leaderboards, search, referral ladders, duration boosts, a GPU miner, an indexer, and embedded custodial wallets.

TASKS.md · deferred, out of scope

part 10

provenance

Gems is a derivative work, and the obligations that come with that are listed here.

10.1

Derived from Equium, under Apache-2.0

Equium implements a single fixed CPU-mineable token. Gems converts that design into a multi-tenant launchpad. The licence is Apache-2.0, inherited, and the NOTICE file carries the statement of changes that section 4(b) of that licence requires.

Files carrying substantive edits are marked in their header comments, so the boundary between inherited and new work stays inspectable rather than asserted.

upstream
github.com/HannaPrints/equium
licence
Apache-2.0

NOTICELICENSE

10.2

The structural changes from Equium

Singleton accounts became per-mint accounts. Compile-time emission constants moved into per-token configuration chosen at launch and frozen. A single launch instruction replaced a deployer-run initialize plus off-chain mint creation. Equium's admin key and its optional renounce step were removed entirely rather than made optional.

Rounds became time-boxed and pro-rata rather than ending on a solution with one winner, difficulty retargeting was deleted, weight became program-custodied stake, and the token mint was bound into the Equihash input block.

NOTICE · statement of changes

10.3

The source is not published yet

Repository paths are cited throughout this paper so that each claim points at the file that has to be read to check it. Those paths are not links, because no public repository has been configured yet.

Until it is, the honest position is that the claims in this document are checkable by whoever holds the source, and not yet by the public.

TASKS.md · release blockers

Gems is derived from Equium and licensed under Apache-2.0. Repository paths in this document are citations, not links: no public repository has been configured yet, so these claims are checkable by whoever holds the source and not yet by the public.