Skip to main content

Error Codes

Reference for all error messages in the Ghost Protocol contracts.

Commitment Errors

ErrorMeaningSolution
InvalidCommitmentCommitment is zero or invalid field elementCheck commitment computation
CommitmentAlreadyExistsDuplicate commitmentGenerate new secrets
InsufficientFeeSent less than 0.001 ETHSend at least 0.001 ETH
RateLimitExceeded>10 commits in one blockWait for next block

Reveal Errors

ErrorMeaningSolution
InvalidRootRoot not in last 100Get fresh root, regenerate proof
NullifierAlreadyUsedAlready revealedCannot reveal twice
InvalidProofProof verification failedCheck public input order, proof format
InvalidRecipientRecipient is zero addressProvide valid recipient

Troubleshooting

InvalidProof

This is the most common error. Check:

  1. Public input order - Must be [root, nullifier, dataHash, recipient]
  2. Proof array order - snarkjs outputs b in different order than contract expects
  3. dataHash mismatch - Off-chain computation must match contract's computeDataHash
  4. nullifier computation - Check the formula uses the correct inputs

InvalidRoot

The root is too old. The protocol only accepts the last 100 roots.

  1. Get the current root from the CommitmentTree
  2. Regenerate your Merkle proof with the new root
  3. Generate a new ZK proof
  4. Retry the reveal

NullifierAlreadyUsed

The commitment has already been revealed. This is permanent.

# Check if nullifier is spent
cast call 0x03972E4453fD143A5203602020DbE2f7DcF6e0db "isSpent(bytes32)(bool)" <nullifier> \
--rpc-url https://testnet-rpc.umbraline.com

InsufficientFee

Send at least 0.001 ETH with your commit transaction.

await walletClient.writeContract({
// ...
value: parseEther('0.001'),
});

Events to Monitor

When debugging, monitor these events:

// Successful commit
event Committed(bytes32 indexed commitment, uint256 indexed leafIndex, uint256 timestamp);

// Successful reveal
event Revealed(bytes32 indexed nullifier, bytes32 indexed dataHash, address indexed recipient);

// Root updates
event RootUpdated(bytes32 indexed oldRoot, bytes32 indexed newRoot, uint256 leafCount);