Supply Mechanics
The GHOST token has a hard-capped supply with zero inflation. All minting and burning is exclusively controlled through the ghostmint precompile, and the supply invariant is checked every block at the consensus level. This page documents the supply parameters, enforcement mechanisms, and tracking infrastructure.
Supply Parameters
| Parameter | Value | Location |
|---|---|---|
| Maximum supply | 1,000,000,000 GHOST (10^27 aghost) | x/ghostmint/types/keys.go (MaxMintSupply) |
| Inflation rate | 0% | x/mint module configuration |
| Denomination | aghost (18 decimals) | Native denom across Cosmos and EVM |
| Smallest unit | 1 aghost | 10^-18 GHOST |
The maximum supply is hard-coded as a Go variable in the ghostmint module:
// MaxMintSupply is the hard cap on total tokens mintable via ghostmint.
// 1 billion GHOST = 1e27 aghost (18 decimals).
MaxMintSupply = math.NewIntFromBigInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(27), nil))
This value is a compile-time constant. Changing it requires a chain upgrade with validator consensus -- it cannot be modified by governance proposals, contract calls, or any runtime mechanism.
Zero Inflation
The Cosmos SDK x/mint module is configured with a 0% inflation rate. No new GHOST tokens are created through block rewards or staking inflation. The only mechanism that creates GHOST tokens is the ghostmint precompile, and it is constrained by the MaxMintSupply cap and the net supply tracking.
Net Supply Tracking
The ghostmint module tracks cumulative minting and burning in its KVStore:
netSupply = totalMinted - totalBurned
Every mint operation checks:
netSupply + mintAmount <= MaxMintSupply
This formula accounts for burns. If 500 million GHOST are minted and 200 million are burned (through privacy commits), the net supply is 300 million. The protocol can still mint up to 700 million more GHOST before hitting the cap. Burns "free up" supply capacity.
KVStore Keys
| Key | Purpose |
|---|---|
TotalMinted | Cumulative aghost minted via ghostmint precompile since genesis |
TotalBurned | Cumulative aghost burned via ghostmint precompile since genesis |
LastTotalSupply | Previous block's total aghost supply (for invariant checking) |
These values are persisted in the module's KVStore and updated atomically with each mint or burn operation.
Ghostmint Precompile
All GHOST minting and burning flows through the ghostmint precompile at address 0x0808. This is the only code path that can create or destroy GHOST tokens (outside of genesis allocation).
| Method | Gas Cost | Description |
|---|---|---|
mintNativeTo(address, uint256) | 50,000 | Mint aghost to recipient via x/bank |
burnNativeFrom(address, uint256) | 50,000 | Burn aghost from sender via x/bank |
totalMinted() | 200 | Read cumulative minted amount |
totalBurned() | 200 | Read cumulative burned amount |
Authorization
The precompile maintains an authorized callers map. Only contracts in this map can call mintNativeTo or burnNativeFrom. Currently, the sole authorized caller is the NativeAssetHandler contract:
| Authorized Caller | Address | Role |
|---|---|---|
| NativeAssetHandler | 0x35cdaE691037fcBb3ff9D0518725F1ae98d502b7 | Bridges CommitRevealVault burn/mint calls to the precompile |
If the authorized callers map is empty (misconfiguration), the precompile rejects all calls -- it does not default to permissive behavior. Additional authorized callers can be added through governance-controlled chain upgrades.
Mint Flow
When mintNativeTo is called:
- Validate the caller is authorized
- Validate amount is positive
- Check
netSupply + amount <= MaxMintSupply - Call
x/bank.MintCoins()to create tokens in the ghostmint module account - Call
x/bank.SendCoinsFromModuleToAccount()to transfer tokens to the recipient - Update
totalMintedin KVStore - Record the balance change in the EVM StateDB journal
Burn Flow
When burnNativeFrom is called:
- Validate the caller is authorized
- Validate amount is positive
- Call
x/bank.SendCoinsFromAccountToModule()to transfer tokens from the precompile address to the ghostmint module account - Call
x/bank.BurnCoins()to destroy the tokens - Update
totalBurnedin KVStore - Record the balance change in the EVM StateDB journal
Supply Invariant
The ghostmint module runs a per-block supply invariant check in the EndBlocker. Every block, the module:
- Reads the current total supply of
aghostfromx/bank - Compares it with the
LastTotalSupplystored from the previous block - If the current supply exceeds the previous supply unexpectedly, logs an error:
SUPPLY INVARIANT: unexpected supply increase
previous: <last block supply>
current: <this block supply>
delta: <unexpected increase>
denom: aghost
- Updates
LastTotalSupplyto the current value for the next block's check
This invariant catches any unexpected supply creation -- whether from a bug in the ghostmint module, a compromised precompile, or any other source. Because the Cosmos SDK's x/bank module tracks total supply independently of the ghostmint module, the invariant provides a cross-check between two independent accounting systems.
Note: The invariant currently logs an error rather than halting the chain. This is a deliberate design choice: halting on an invariant violation would require manual intervention to restart, which could be worse than the violation itself in some scenarios. Future versions may escalate to a chain halt for critical violations.
Solvency Tracking
At the smart contract level, the CommitRevealVault and BatchCommitRevealVault independently track total committed and total revealed amounts per token:
totalRevealed[token] <= totalCommitted[token]
This invariant ensures that the vault never mints more tokens than were burned. It operates at the EVM level and is independent of the consensus-level supply invariant -- providing defense in depth.
Supply Summary
| Layer | Invariant | Enforcement |
|---|---|---|
| Consensus (Go) | netSupply <= MaxMintSupply | Mint rejected if cap exceeded |
| Consensus (Go) | Supply does not increase unexpectedly between blocks | EndBlocker check, error logged |
| EVM (Solidity) | totalRevealed[token] <= totalCommitted[token] | Reveal rejected if solvency violated |
| EVM (Solidity) | Only authorized callers can invoke precompile | Unauthorized calls rejected |