Cosmos-EVM Integration
This page explains why Specter requires its own Layer 1 blockchain, how the Cosmos SDK and EVM execution environment work together, and the technical details of the ghostmint precompile that makes Ghost Protocol possible.
The Problem
Ghost Protocol's commit/reveal model requires two operations that are impossible on standard EVM chains:
-
Burn native tokens from a smart contract. On commit, the user's tokens must be destroyed — not transferred to a contract, not locked, but actually removed from total supply. If tokens are merely locked in a contract, the contract itself becomes a traceable pool (as with Tornado Cash).
-
Mint native tokens from a smart contract. On reveal, fresh tokens must be created and sent to the recipient. These tokens must be indistinguishable from any other native tokens — they are not wrapped, not synthetic, and not IOUs.
On Ethereum and all standard EVM chains, the native token (ETH) exists outside the EVM's control. There is no opcode to mint or burn ETH. Only CALL with a value can transfer it, and the total supply is determined by block rewards and EIP-1559 burns at the protocol level. No smart contract can create or destroy ETH.
This limitation means Ghost Protocol cannot operate as a set of smart contracts on Ethereum, Base, Arbitrum, or any other existing EVM chain — at least not for the native token. While ERC-20 tokens can be burned (by sending to a dead address or using a burn() function), this does not solve the problem for the native gas token, and creating a wrapped representation reintroduces the traceability problem.
The Solution: x/ghostmint
Specter solves this by running its own Cosmos SDK blockchain with a custom module called x/ghostmint. This module exposes an EVM precompile — a special contract-like interface available at a hardcoded address that executes native Go code instead of EVM bytecode.
Architecture
How It Works
1. Precompile Registration
At chain genesis, the x/ghostmint module registers an EVM precompile at address 0x0808. This means any EVM contract can issue a CALL to 0x0808 with encoded parameters, and instead of executing EVM bytecode, the chain's Go runtime handles the call.
The precompile implements the standard Ethereum precompile interface:
type GhostMintPrecompile struct {
bankKeeper bankkeeper.Keeper
authorized map[common.Address]bool
}
func (p *GhostMintPrecompile) Run(input []byte) ([]byte, error) {
// Decode ABI-encoded input
// Verify caller is authorized (NativeAssetHandler)
// Execute mint or burn via bankKeeper
// Return ABI-encoded result
}
2. Authorization
Not every contract can mint or burn native tokens. The precompile maintains an allowlist of authorized callers. In practice, only NativeAssetHandler is authorized. This contract is deployed at chain initialization, and its address is registered with the precompile.
If any other contract attempts to call 0x0808, the precompile reverts.
3. Mint Operation
When CommitRevealVault.reveal() needs to mint GHOST for the recipient:
CommitRevealVault → NativeAssetHandler.mint(recipient, amount)
→ NativeAssetHandler calls 0x0808 with ABI-encoded mint(recipient, amount)
→ ghostmint precompile decodes parameters
→ ghostmint calls bankKeeper.MintCoins(moduleName, sdk.NewCoin("aghost", amount))
→ ghostmint calls bankKeeper.SendCoinsFromModuleToAccount(moduleName, recipientAddr, coins)
→ recipient's balance increases by amount
→ total supply of aghost increases by amount
The minted tokens are real native aghost — identical in every way to tokens earned from staking rewards or received in a normal transfer. There is no wrapper, no synthetic representation, and no way to distinguish minted-via-reveal tokens from any other tokens.
4. Burn Operation
When CommitRevealVault.commit() needs to burn GHOST from the committer:
CommitRevealVault → NativeAssetHandler.burn(user, amount)
→ NativeAssetHandler calls 0x0808 with ABI-encoded burn(amount)
→ ghostmint precompile decodes parameters
→ ghostmint calls bankKeeper.SendCoinsFromAccountToModule(userAddr, moduleName, coins)
→ ghostmint calls bankKeeper.BurnCoins(moduleName, coins)
→ user's balance decreases by amount
→ total supply of aghost decreases by amount
The tokens are permanently destroyed. They do not sit in a contract. They do not exist in any account. The total supply decreases. This is what makes commits untraceable — there is no pool of locked tokens that can be analyzed.
NativeAssetHandler Contract
NativeAssetHandler is the choke point between the EVM world and the Cosmos native token world. Its role is strictly limited:
contract NativeAssetHandler {
address constant GHOSTMINT_PRECOMPILE = 0x0000000000000000000000000000000000000808;
address public vault; // CommitRevealVault address
modifier onlyVault() {
require(msg.sender == vault, "unauthorized");
_;
}
function mint(address recipient, uint256 amount) external onlyVault {
// ABI-encode the mint call and invoke the precompile
(bool success, ) = GHOSTMINT_PRECOMPILE.call(
abi.encodeWithSignature("mint(address,uint256)", recipient, amount)
);
require(success, "mint failed");
}
function burn(uint256 amount) external payable onlyVault {
// ABI-encode the burn call and invoke the precompile
(bool success, ) = GHOSTMINT_PRECOMPILE.call(
abi.encodeWithSignature("burn(uint256)", amount)
);
require(success, "burn failed");
}
}
This two-layer authorization (only vault can call NativeAssetHandler; only NativeAssetHandler can call the precompile) ensures that native token minting and burning can only happen through the Ghost Protocol pipeline.
CometBFT Consensus
Specter uses CometBFT (formerly Tendermint) as its consensus engine.
Properties
| Property | Value |
|---|---|
| Block time | ~5 seconds |
| Finality | Instant (single-slot finality). Once a block is committed, it cannot be reverted. |
| Fault tolerance | Tolerates up to 1/3 of validators being Byzantine (offline, malicious, or compromised). |
| Validator set | Proof-of-Stake. Validators are selected by delegation weight. |
Why CometBFT Matters for Privacy
Instant finality is important for Ghost Protocol:
- No reorgs. On probabilistic-finality chains (e.g., Ethereum pre-merge), a commitment could be included in a block that is later reorged out. This would require the user to recommit, potentially leaking information through the retry pattern. CometBFT guarantees that once a commitment is in a block, it stays.
- Fast confirmation. Users know their commit is final in ~5 seconds, not 12+ minutes. This matters for physical card flows where a user taps an NFC card and expects immediate confirmation.
Cosmos SDK Modules
Beyond x/ghostmint, Specter uses the standard Cosmos SDK module set:
x/bank
Manages all native token balances. Every aghost balance, transfer, mint, and burn flows through x/bank. The module maintains:
- Per-account balances
- Total supply tracking
- Denomination metadata (
aghost, 18 decimals, display denomGHOST)
x/staking
Proof-of-Stake validator management:
- Validators bond GHOST tokens to participate in consensus.
- Delegators stake GHOST to validators and earn rewards.
- Unbonding period protects against long-range attacks.
x/gov
On-chain governance:
- Token holders submit and vote on proposals.
- Proposals can modify chain parameters, upgrade software, or allocate community funds.
- Governance controls critical parameters like the
ghostmintauthorized caller list.
x/distribution
Reward distribution:
- Block rewards and transaction fees are collected by the distribution module.
- Rewards are distributed to validators proportional to their voting power.
- Validators share rewards with their delegators minus a commission.
x/slashing
Validator accountability:
- Validators who go offline (miss too many blocks) are jailed and slashed.
- Validators who double-sign are permanently jailed (tombstoned) and heavily slashed.
- Slashing protects the network from unreliable or malicious validators.
x/evidence
Misbehavior processing:
- Accepts evidence of double-signing or other protocol violations.
- Triggers slashing and jailing through
x/slashing.
Address Formats
Specter supports two address formats corresponding to its two execution environments:
| Format | Example | Usage |
|---|---|---|
| Bech32 | umbra1qpzm7v8rvf3hx5jg6nxm0dcqzwt... | Cosmos SDK transactions, staking, governance, bank transfers |
| Hex (EIP-55) | 0x742d35Cc6634C0532925a3b844... | EVM transactions, smart contract interactions |
Both formats refer to the same underlying account. The chain automatically converts between them. A user with a MetaMask wallet interacts via the hex address; the same account's staked GHOST appears under the bech32 address in Cosmos tooling.
The bech32 prefix umbra is used for all Cosmos-side addresses:
| Prefix | Usage |
|---|---|
umbra | Account addresses |
umbravaloper | Validator operator addresses |
umbravalcons | Validator consensus addresses |
umbrapub | Account public keys |
umbravaloperpub | Validator operator public keys |
umbravalconspub | Validator consensus public keys |
Why Not Just Deploy on an Existing Chain?
A summary of the trade-offs:
| Approach | Native mint/burn | Privacy model | Sovereignty | Trade-off |
|---|---|---|---|---|
| Contracts on Ethereum | No | Pool-based (traceable contract) | None (subject to Ethereum governance) | Cannot implement true commit/reveal for native token |
| L2 rollup | No (inherits L1 native token) | Pool-based | Partial | Same native token limitation |
| Cosmos appchain (Specter) | Yes (ghostmint precompile) | True mint/burn (no pool) | Full (own validators, governance) | Must bootstrap validator set and liquidity |
Specter accepts the cost of running its own validator set and bootstrapping liquidity in exchange for the ability to implement Ghost Protocol correctly — with real native token destruction on commit and creation on reveal, no traceable token pools, and full sovereignty over protocol-level privacy infrastructure.