Skip to main content

Ghostmint Usage Examples

Reading supply statistics

These are view functions that anyone can call:

# Total GHOST minted through precompile
cast call 0x0000000000000000000000000000000000000808 \
"totalMinted()(uint256)" \
--rpc-url https://testnet.specterchain.com

# Total GHOST burned through precompile
cast call 0x0000000000000000000000000000000000000808 \
"totalBurned()(uint256)" \
--rpc-url https://testnet.specterchain.com
import { createPublicClient, http } from 'viem';

const client = createPublicClient({
transport: http('https://testnet.specterchain.com'),
});

const ghostmintAbi = [
{ name: 'totalMinted', type: 'function', inputs: [], outputs: [{ type: 'uint256' }], stateMutability: 'view' },
{ name: 'totalBurned', type: 'function', inputs: [], outputs: [{ type: 'uint256' }], stateMutability: 'view' },
];

const totalMinted = await client.readContract({
address: '0x0000000000000000000000000000000000000808',
abi: ghostmintAbi,
functionName: 'totalMinted',
});

const totalBurned = await client.readContract({
address: '0x0000000000000000000000000000000000000808',
abi: ghostmintAbi,
functionName: 'totalBurned',
});

console.log('Net supply delta:', totalMinted - totalBurned);

How NativeAssetHandler calls the precompile

The NativeAssetHandler is the reference implementation of an authorized precompile caller:

// Simplified from NativeAssetHandler.sol
contract NativeAssetHandler {
address public constant MINT_PRECOMPILE = 0x0000000000000000000000000000000000000808;

function mintNativeTo(address to, uint256 amount) external onlyVault {
(bool success,) = MINT_PRECOMPILE.call(
abi.encodeWithSignature("mintNativeTo(address,uint256)", to, amount)
);
require(success, "Mint failed");
}

function burnNativeFrom(address from, uint256 amount) external payable onlyVault {
(bool success,) = MINT_PRECOMPILE.call{value: msg.value}(
abi.encodeWithSignature("burnNativeFrom(address,uint256)", from, amount)
);
require(success, "Burn failed");
}
}

Writing an authorized caller

If your contract were authorized via governance, this is the pattern for calling the precompile:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

interface IGhostmint {
function mintNativeTo(address recipient, uint256 amount) external returns (bool);
function burnNativeFrom(address from, uint256 amount) external payable returns (bool);
}

contract MyAuthorizedContract {
IGhostmint constant GHOSTMINT = IGhostmint(0x0000000000000000000000000000000000000808);

function mintTokens(address to, uint256 amount) external {
bool success = GHOSTMINT.mintNativeTo(to, amount);
require(success, "Mint failed");
}

function burnTokens(uint256 amount) external payable {
bool success = GHOSTMINT.burnNativeFrom{value: msg.value}(msg.sender, amount);
require(success, "Burn failed");
}
}
warning

This contract would need governance authorization before mintNativeTo or burnNativeFrom calls would succeed. Without authorization, these calls revert.