Monthly Archives: September 2022

Andrew Parker’s Sybil-Resistant User-Operated NFT Minting Mechanism

Never mind that NFTs have rolled off the hype cycle’s peak of inflated expectations and now grind through an unknowably-long trough of disillusionment! Let’s revisit Andrew Parker’s mechanism for end-user NFT minting, and make some technical cleanups and tweaks such that NFT contracts extract maximum fees from minters.

NB: there’s no code in here, so if you’re expecting to find something to copy/paste into the contract that some ding dong on Fiverr is paying you to cobble together, you can just scram, kid. As I say at the office from time to time, my job is (tragically) not to write code any longer, but to help you figure out what code to write.

Definitions

  • Minting
    Creating a new token in an NFT contract.
  • Premine
    Old-school scam wherein a select number of individuals operate a blockchain in secret and private before exposing its critical values to the rest of the internet for public mining, thereby safely reserving an unholy pile of the shitcoin for the initial operators themselves without competition against the rest of the universe of hashpower. Satoshi is the original premine case, which is how you know that Bitcoin is a scam.
  • Gas
    The cost of including a transaction in an Ethereum block. Dynamic, like Bitcoin transaction fees, based on current demand for block space.

Current Minting Challenges

NFT drops, premints and user-operated minting and so on generally suffer on a few common axes: mishandled manual allocations, sophisticated contract operators out-performing naive humans, and egregious gas fees.

Manual allocations are when NFT contract authors (or their marketing agencies) sell or give away individual tokens or token-minting rights before the contract hits the blockchain[1]In some cases, the NFT contract can be updated by its authors or maintainers, but I’ll neglect this case for now, excommunicating such misbehavior as cryptographic heresy. Manual allocations are sometimes implemented with some kind of pre-computed list (dumb) embedded in the contract (wasteful) blessing specified addresses with permissions to call various NFT minting methods, or in the dumbest possible cases, the contract authors themselves are the only ones allowed to “mint” NFTs and then variously hand the tokens out or auction them. All of the above implementations are stupid, poorly factored, and generally suck (and moreover point towards the comic ignorance of NFT contract authors of pretty much all prior art in the space), but can be understood in the context of contract authors attempting to milk their mints/drops for as much end-user cash as possible.

A smaller number of Ethereum contracts by JavaScript developers with delusions of grandeur (those who bother to look will find a Lisp in the historical detritus. No points for guessing why that never made it into the DevRel propaganda…) attempt to solve this problem by hardcoding rules like “any given wallet can only mint N tokens per Q blocks” into the contract. I find this even more tragically stupid than the premine strategies (which are at least not stupid and intellectually honest insofar as the implementation is saying: “these are my enn eff tees and you can have them for a price that I set”), because it conflates individuals with addresses, something that Bitcoin lore disposed of purt goddamn near a decade back. The poor schmucks who attempt this strategy are so unfortunate that nobody around them is smart enough to whisper “sybil attack” in their ears, and so they go about blissfully unaware of the entire corpus of literature until they release their contract and it gets pwned on day zero by someone with a college-prep high-schooler’s mathematical savvy. This is like inventing scalable session handling by storing session data in individual web heads, pushing that sticky session notion into your load balancer, and then wondering why new nodes in your autoscaling pool don’t serve as much traffic as old nodes. In 2027.

Egregious gas fees are the final failure mode I find worth talking about, because these are typically also a symptom of unqualified engineers mucking about with mathematical systems they don’t really understand. During exceptionally hype-frothy NFT minting event the sheer number of people attempting to call methods on the popular contracts to mint tokens explodes the demand side for Ethereum block storage space. Naturally, those who bid the highest get their transactions confirmed, and everyone else misses out. Not just everyone else competing for block space to support the particularly popular transaction, but everyone on the entire Ethereum network now competes against folks tryna get their mitts on the latest cryptowhatever, which is not just a spectacular waste of the NFT squad’s money (hey, I love me a deflationary cryptosystem, don’t get me wrong), but of everyone’s money who might be attempting to use Ethereum for…something useful. Assuming such applications exist. But I digress.

Design Goals

  • Low gas fees
  • Arbitrary users can mint NFTs
  • No off-chain trust mechanisms
  • Minting mechanisms can’t be spammed
  • NFT authors capture some fraction of the demand otherwise spent on gas fees
  • Thwart front-running

Design

Proof-of-work.

That’s probably not enough to go on (tee hee hee), so I’ll sketch out the fundamental mechanism for those unfamiliar with how Bitcoin solves this exact same problem.

The minting method must accept payment, and has a signature of:

mint :: str -> ()

Where that str argument is the nonce used to prove that work has been done.

Hashing implementation

  1. Concatenate:
    1. mint function caller’s address
    2. supplied nonce
  2. Hash output of 1.

Difficulty (and the ultimate input)

Bitcoin adjusts difficulty every so often by comparing how quickly blocks were generated with a desired production rate and then ratcheting up or down the required number of leading zeros from the output of hashing some well-known data (neé nonce).

In an NFT implementing this interface, you’ll track difficulty in the exact same way: calculating how many leading zeros your hash function needs to output in order for the contract to consider the nonce valid for NFT minting.

Since mining is a proxy (syntactic sugar) for the minter’s ability to buy the NFTs they want to mint, shouldn’t we just give folks the ability to buy NFTs over the counter, without any of this complicated hashing stuff? If the buy-side is prone to literally throwing money away on gas fees during times of competition for block space, how can we capture that cash that’s otherwise being lit on fire during minting races?

To effectively capture the gas market, simply add the order of magnitude of wei sent along with the minting transaction to the number of leading zeros from the hash output, and if the total number of zeros is greater than the current difficulty number, mint a new NFT.

Departures from Parker

  1. Dynamically calibrate difficulty after every minting event to ensure desired output characteristics
  2. Incorporate payments to augment pure hash difficulty
  3. Don’t require the previous token’s hash in minting
    This is probably the most controversial proposal. I contend that if you check to see if difficulty needs adjustment after every single minting event, you can ensure that even if an infinite number of mintings are submitted in a single block, the adjustment recalculation will ensure that as soon as your difficulty threshold exceeds that which is supplied in the infinite series, all other minting transactions will be tossed. For this we have the serial nature of block construction in Ethereum to thank 🙂

Design Goal Evaluation

  • Low gas fees
    Check, gas auction dynamics are captured by the payable minting function, and concatenating the number of zeros of wei along with the leading zeros of the hash output to get final hash strength.
  • Arbitrary users can mint NFTs
    Check.
  • No off-chain trust mechanisms
    Check.
  • Minting mechanisms can’t be spammed
    Check.
  • NFT authors capture some fraction of the demand otherwise spent on gas fees
    Check.
  • Thwart front-running

References

References
1In some cases, the NFT contract can be updated by its authors or maintainers, but I’ll neglect this case for now, excommunicating such misbehavior as cryptographic heresy