Loading...
In the previous blog post, I described how I set up an image generator that quite nicely fulfills my needs: The generator in the background is open-source, I have full cost control, I made the system easily usable to others and it is really privacy-conserving. However, I could not resist the temptation to make it easier for others to see some of the images and to try to set up small incentive systems in the form of collector NFTs. The main changes are:
They are all nicely visible in the screen shot below.
Let me describe here, which major changes I made and give you some of the technical details.
I really enjoy the playful approach to image generation. But a lot of them fail and I do not really want to keep or share them. Hence, it is really easy to delete them from the blockchain and they are NOT listed to the public gallery by default. However, for a few of them I would actually be quite happy to share them with others. Hence, I added a simple new attribute to the smart contract, which is called isListed
and set to false
by default. The functionality is simple:
true
, the image is listed in the public gallery.false
, the image is not listed and can only be seen in the other tab.This is a super simple approach, which is inspired by the robots.txt approach. It does not securely make things private, but it unlists them from some public galleries. This approach is inspired by robots.txt - just as robots.txt doesn't technically prevent access but signals to web crawlers whether content should be indexed, the isListed
flag signals whether an image should appear in public galleries. The data remains on the blockchain and is technically accessible, but won't be displayed in the public interface.
I had already set up the smart contract to be upgradeable with OpenZeppelin. However, initially I really enjoyed the work with hardhat ignition (a deployment tool) and viem (a TypeScript library for Ethereum). So I tried to make the upgrades work with these tools for quite some time. The main issue was that Hardhat Ignition and Viem don't have built-in support for OpenZeppelin's upgrade patterns.
In the end it never really worked out and everything became much easier when I left hardhat ignition behind and simply used the OpenZeppelin Hardhat Upgrades plugin. The OpenZeppelin Hardhat Upgrades plugin handles the complex proxy logic automatically, including storage layout validation and initialization functions.
This unfortunately means that I have to change the deployment stack for the smart contracts completely. However, Claude Sonnet has proven to be a great friend for the corresponding code. I am still not proud about it, but it works good enough for now.
The updates to the imagegen website were rather straightforward (again thanks to Claude Sonnet). I introduced a new tab which shows public images to anyone on the website. The functionality is obviously a bit different from the private tab, but overall the changes were fairly minimal.
Once I was able to list images in the public gallery, I also wanted to allow others to collect them. The logic behind the little collect button is similar to the support system for the blogs but a bit more evolved. In the contract for the support system, I implemented a simple mapping between the supported address and the number of supporters. Once you hit the support button, a small fee is sent to a specified address and the number of supporters is increased by one. However, this does not really create a market for the supported content and is very much a donation system.
In the case of the image generator, I wanted to go a step further. So I set up the system in the following fashion:
The whole thing is about artwork. So you have the strong feeling that it should be more expensive to collect "popular" art than the one from an unknown street artist. However, in a standard approach of unlimited collector NFTs, a collector could never achieve a price gain because any additional supporter would simply mint another NFT and that's it.
Therefore, I decided to introduce an exponential increase in the mint price of the collector NFTs. The pricing follows an exponential progression where the price doubles with each batch of collectors:
This means if you're the 12th collector, you pay 0.004 ETH, but if someone becomes the 27th collector later, your NFT becomes more valuable as the entry price has increased to 0.032 ETH.
This can solve a number of open questions:
As I worked on the CollectorNFT
, I had to fix a few bugs and wanted to implement them in an upgrade. However, at that point I discovered that OpenZeppelin actually uses annotations to mark certain functions. And these annotations are really important when you work with the upgradeable plugins as they help you to secure the contract. They are not documented super well, but if you try to introduce them later on, they break the upgrades. So better introduce them early on.
The key lesson: OpenZeppelin uses special annotations like @custom:oz-upgrades-unsafe-allow
to mark functions that might be dangerous in upgradeable contracts. These annotations must be present from the beginning - adding them later breaks the upgrade mechanism because the plugin validates the entire contract history.
It is super stimulating to work on this kind of topics as they allow me to play around with new ideas which have plenty of possibilities.
This project demonstrates how blockchain technology can create sustainable creator economies for AI-generated art. The combination of public galleries, collector NFTs, and exponential pricing creates interesting dynamics that traditional platforms can't replicate.
Next steps I'm considering:
You can try the system yourself at imagegen - I'd love to see what images you create and whether anyone finds them worth collecting. The source code for both the smart contracts and frontend is available in my GitHub repository.