GhostERC20
GhostERC20 is a privacy-compatible ERC-20 token designed for use within the Specter protocol. It extends the standard OpenZeppelin ERC-20 implementation with Specter-specific features: a Poseidon-based token ID hash for use inside ZK circuits, ghost registration with AssetGuard, and authorized mint/burn capabilities.
Token ID Hash
Each GhostERC20 token computes a unique identifier used inside ZK-SNARK circuits:
bytes32 public tokenIdHash;
The hash is computed as:
tokenIdHash = Poseidon2(uint256(uint160(address(this))), 0)
This uses the PoseidonT3 library (Poseidon with t=3, meaning 2 inputs and 1 output). The token's address is cast to uint256 and hashed with a zero constant. This deterministic hash is included in ZK proofs to bind withdrawals to specific token types without revealing on-chain which token is involved.
Functions
enableGhost
function enableGhost() external
Registers this token with the AssetGuard contract, authorizing it for deposits into the CommitRevealVault.
Access control: Only the token deployer (owner) can call this function. Typically called immediately after deployment by the GhostERC20Factory.
Behavior:
- Calls
AssetGuard.recordDeployment(address(this), factory). - Computes and stores the
tokenIdHashviaPoseidonT3. - Marks the token as ghost-enabled (prevents double-registration).
Reverts if:
- Already ghost-enabled.
- Caller is not the owner.
mint
function mint(address to, uint256 amount) external
Mints new tokens to the specified address.
Parameters:
| Name | Type | Description |
|---|---|---|
to | address | Recipient of the minted tokens. |
amount | uint256 | Number of tokens to mint (in the token's smallest unit). |
Access control: Only authorized minters can call this function. The CommitRevealVault is typically the primary authorized minter.
Reverts if:
- Caller is not an authorized minter.
tois the zero address.
burn
function burn(address from, uint256 amount) external
Burns tokens from the specified address.
Parameters:
| Name | Type | Description |
|---|---|---|
from | address | Address whose tokens will be burned. |
amount | uint256 | Number of tokens to burn. |
Access control: Only authorized minters (e.g., the vault) can call this function.
Reverts if:
- Caller is not an authorized minter.
fromhas insufficient balance.
Inherited ERC-20 Functions
GhostERC20 inherits the full OpenZeppelin ERC-20 interface:
| Function | Description |
|---|---|
name() | Returns the token name. |
symbol() | Returns the token symbol. |
decimals() | Returns the number of decimals. |
totalSupply() | Returns the total supply. |
balanceOf(address) | Returns the balance of an account. |
transfer(address, uint256) | Transfers tokens to a recipient. |
allowance(address, address) | Returns the remaining allowance. |
approve(address, uint256) | Sets an allowance for a spender. |
transferFrom(address, address, uint256) | Transfers tokens using an allowance. |
Constructor
constructor(
string memory name_,
string memory symbol_,
uint8 decimals_,
address assetGuard_,
address poseidonT3_
)
| Parameter | Description |
|---|---|
name_ | Human-readable token name (e.g., "Ghost USDC"). |
symbol_ | Token ticker symbol (e.g., "gUSDC"). |
decimals_ | Number of decimal places (e.g., 18). |
assetGuard_ | Address of the AssetGuard contract. |
poseidonT3_ | Address of the deployed PoseidonT3 library. |
Usage Example
Deploying and Enabling a GhostERC20
// Normally done via GhostERC20Factory, but shown here for clarity:
GhostERC20 token = new GhostERC20(
"Ghost USDC",
"gUSDC",
6,
assetGuardAddress,
poseidonT3Address
);
// Register with AssetGuard
token.enableGhost();
// Now the token can be deposited into CommitRevealVault
// token.tokenIdHash() returns the Poseidon hash for ZK circuits
Using tokenIdHash in Proofs
// Off-chain (JavaScript/TypeScript SDK):
const tokenAddress = "0x...";
const tokenIdHash = poseidon2(BigInt(tokenAddress), 0n);
// This value is used as a public input to the ZK proof circuit
// and must match the on-chain token.tokenIdHash()
Security Notes
- The
tokenIdHashis deterministic and public. It does not leak any private information; it simply provides a field-element representation of the token address for use in arithmetic circuits. - Mint and burn functions are access-controlled to prevent unauthorized supply manipulation. The vault is the expected caller during reveal operations.
- Standard ERC-20 transfers remain fully functional. Users can hold, transfer, and trade
GhostERC20tokens outside the privacy system.