
Launched on July 29, 2016, BeerCoin is one of the oldest NFT projects on the Ethereum blockchain. It was created by Nick Johnson, the eventual founder of Ethereum Name Service (ENS), for the purpose of issuing (non-binding and just-for-fun) beer IOUs (see original announcement here).
In theory, infinitely many IOUs can be issued. However, at the end of 2017, only 94 beers were owed in total. The state of the contract was left unchanged from 2018-2020, and then people started playing around with it in 2021.
A stepping stone on the way to the ERC-721 standard for modern NFTs, the BeerCoin project holds a special place in Ethereum history. The 94 IOUs originating in that 2016-17 time period are indeed rare digital artifacts.
Wrapper Contract
I first came across the BeerCoin contract in 2021, and I decided to try to (1) acquire one of the original IOUs, and (2) create a wrapper contract so that all holders of original IOUs could tokenize them and trade them as collectibles on the NFT marketplaces.
Nick Johnson was nice enough to offer one up in exchange for this BeerCoin-enthusiast romantic-partner NFT (a story for another time). Following the trade, I got down to work on the wrapper, which has now been deployed. You can view the BeerCoins that have been wrapped on OpenSea.
Here is an overview of the wrapping and unwrapping processes.
Suppose address C is owed n beers by address D in the original BeerCoin contract. The wrapper creates a special holding address H, and during the wrapping process, C transfers the IOU to H in exchange for an ERC-721 token.
Note that some addresses are owed multiple beers by a single address. The wrapper only issues one token per debtor-creditor pair, so only 77 can be minted, rather than 94. If a token involves multiple beers, this will be indicated in the metadata.
During the unwrapping process, the token holder C burns the token, and the IOU is transferred from the holding address H to C.
The details of the wrapping and unwrapping procedures are as follows.
Wrapping
Let’s assume that you are on the list of creditors as being owed n beers by D. Further, let’s call the address of the wrapper contract W.
Step 1: In the original contract, call approve(W, n) to give the wrapper contract permission to transfer your IOU to a holder.
Step 2: In the wrapper contract, call Wrap(D) to move the IOU to a holder and receive a corresponding token.
Unwrapping
Now suppose you are holding a token with ID i, which corresponds to a debt of n beers.
Step 1: If the IOU involves multiple beers, then you must call setMaximumCredit(n) in the original contract. By default, an address has a credit limit of one beer.
Step 2: In the wrapper contract, call Unwrap(i). This causes the token to be burned, and the IOU moves from the holder to your address.
A Few Words of Warning
To determine the debtor-creditor pairs for the 2016-17 timespan, I reviewed all of the transactions of the original contract. At the time of this writing, I am confident that if address C is on the list as being owed n beers by address D, that debt is indeed one that originated between 2016 and 2017.
Permission to wrap is based on address, and this has certain implications. First, the original holder must do the wrapping. If they transfer the IOU to another address, it’s still a valid old IOU, but it will be rejected by the wrapper contract. Second, IOUs cannot be rewrapped once they have been unwrapped.
Also, despite the restrictions on who can wrap, it’s still possible for certain shenanigans to take place. Say C holds an old IOU from D. If it wanted to, C could transfer that IOU to someone else, ask D for a new IOU, and then mint the new IOU as a token. Since the wrapper contract’s permissions are based on address only, it will allow this fraudulent token to be created. It’s highly unlikely that this will happen, and it would be detectable through inspection of the transaction history.
In addition to people misusing the wrapper contract, there could be flaws in the contract itself. I did my best to write a wrapper that issues valid tokens and preserves provenance, but I can provide no guarantees.
The bottom line is that it is essential for you to do your own research before interacting with the wrapper contract. Read the code for both the original and wrapper contracts, and study all of the transactions. Dealing with old projects and wrapper contracts is for advanced users only. Proceed at your own risk!