Signature Validation (EIP-712)

dotHYPE uses off-chain signatures verified on-chain to secure mints, prevent front-running, and lock pricing. This page explains how the system works for users and developers.

Signature-based minting enables secure, gas-efficient registrations while giving users confidence that prices can’t be manipulated between signing and minting.

🔒 Why Signatures Matter

When public mints are open, smart contracts are vulnerable to bots or MEV frontrunners:

  • A user submits a transaction

  • A bot sees it in the mempool

  • The bot re-submits the transaction with higher gas to claim the name first

To prevent this, dotHYPE uses EIP-712 typed data signatures. These allow us to:

  • Pre-authorize name mints with fixed pricing

  • Let users sign intent off-chain before paying gas

  • Limit signature usage to one-time only via nonces

🧾 Signature Structure

All signatures must match this typed data structure:

struct SignatureData {
  string name;         // Name to register
  address owner;       // Recipient of the NFT
  uint256 duration;    // Registration period (in seconds)
  uint256 maxPrice;    // Max price user is willing to pay
  uint256 deadline;    // Expiry time for the signature
  uint256 nonce;       // Prevents reuse
}

This structure ensures signatures can’t be reused, expire after a window, and guarantee pricing.

🔁 Signature Minting Flow

function registerWithSignature(
  string calldata name,
  address owner,
  uint256 duration,
  uint256 maxPrice,
  uint256 deadline,
  uint256 nonce,
  bytes calldata signature
) external payable returns (uint256 tokenId, uint256 expiresAt);

The flow:

  1. An authorized signer generates the EIP-712 payload with mint parameters

  2. User submits the signature in the mint UI

  3. Controller contract verifies:

    • Signature is valid

    • It hasn’t expired

    • Nonce hasn’t been used

    • Price is <= maxPrice

  4. If valid, the Controller proceeds to register the name and mint

🔄 Nonce Management

Each user has a nonce that increments with every successful mint:

mapping(address => uint256) public nonces;
function getNextNonce(address owner) external view returns (uint256);

This prevents replay attacks and ensures signatures are single-use only.

🔐 Security Guarantees

Signature-based minting protects users by:

  • Enforcing a maximum price set during signing

  • Expiring signatures with a deadline timestamp

  • Locking out re-use via per-user nonce

If any of these checks fail, the transaction is rejected without consuming gas beyond call overhead.

⚙️ Setting the Signer

Only the protocol owner can set or change the authorized signer address:

function setSigner(address _signer) external onlyOwner;

This signer is used to validate all signature-based registration requests.

🛡 Best Practices

If you’re building or operating the signature system:

  • Always generate EIP-712 payloads client-side or in secure backend infra

  • Use getNextNonce() before generating a signature

  • Set tight deadline windows to minimize signature misuse

Never share the private key of the signer, and rotate regularly if compromised.

🧠 For Developers

If you’re integrating:

  • Use our SDK or libraries to generate the proper EIP-712 payload

  • Submit via registerWithSignature() in the Controller

  • Always check availability before generating the signature

Want to learn how signature minting fits into the broader system? See the Minting Flow → overview.

Last updated