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:
An authorized signer generates the EIP-712 payload with mint parameters
User submits the signature in the mint UI
Controller contract verifies:
Signature is valid
It hasn’t expired
Nonce hasn’t been used
Price is <=
maxPrice
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 signatureSet 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 ControllerAlways check availability before generating the signature
Want to learn how signature minting fits into the broader system? See the Minting Flow → overview.
Last updated