An NFT sale is a function call that creates tokens under conditions written into the contract. Supply caps, wallet limits and eligibility checks are enforced there, not by the website taking orders.
The cap is a comparison, not a promise
A maximum supply is typically a constant checked against a counter each time the mint function runs. Exceeding it causes the transaction to revert.
This is why a stated supply is verifiable. Anyone can read the constant and the counter, and neither depends on the project honoring what its marketing said.
The check only binds the function that contains it. A separate function reachable by the owner can mint outside the public path unless the contract explicitly forbids it.
Per-wallet limits are weaker than they look
Limiting mints per address requires storing how many each address has taken, which costs storage and therefore gas on every mint.
The limit constrains addresses rather than people. Creating additional addresses is free, so the restriction shapes convenience more than it shapes distribution.
Contracts sometimes reject calls from other contracts to block batch minting, though that also blocks smart contract wallets used by ordinary buyers.
Allowlists are proved, not stored
Storing thousands of eligible addresses on chain would be expensive, so contracts store a single hash summarizing the whole list instead.
A buyer supplies a proof alongside their mint call, and the contract verifies that combining the proof with their address reproduces the stored hash.
Eligibility is therefore checked without the contract ever holding the list. Updating the list means publishing a new hash, which invalidates every previously issued proof.
Reveal is a pointer change
Many sales mint tokens whose metadata pointer initially resolves to a placeholder, with the real pointer set afterward by the contract owner.
This exists because publishing metadata before the sale would let buyers identify desirable tokens and target specific identifiers during minting.
It also means the owner controls what each token becomes until the pointer is frozen. Contracts that permanently lock the base pointer remove that discretion.
Randomness has to come from somewhere
Assigning traits fairly requires a random value, and blockchains are deterministic by design, so no genuinely random number exists inside the contract.
Using block data as a seed is predictable to whoever produces the block, which creates an opening for the assignment to be influenced.
Projects that care about this use an external randomness service or commit to a shuffle after minting closes, so the ordering cannot be known while tokens are still being sold.