Skip to main content

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:

  1. Calls AssetGuard.recordDeployment(address(this), factory).
  2. Computes and stores the tokenIdHash via PoseidonT3.
  3. 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:

NameTypeDescription
toaddressRecipient of the minted tokens.
amountuint256Number 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.
  • to is the zero address.

burn

function burn(address from, uint256 amount) external

Burns tokens from the specified address.

Parameters:

NameTypeDescription
fromaddressAddress whose tokens will be burned.
amountuint256Number 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.
  • from has insufficient balance.

Inherited ERC-20 Functions

GhostERC20 inherits the full OpenZeppelin ERC-20 interface:

FunctionDescription
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_
)
ParameterDescription
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 tokenIdHash is 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 GhostERC20 tokens outside the privacy system.