WarpFlow is a fully-onchain NFT collection containing approximately 1000 possible combinations of pixel-art spaceships, each with approximately one of 25000 real-world warship names. I built it for the Flow internal hackathon for spring 2025. I worked alone on this project.
The project originated after a conversation with Zach, our resident tokenomics and defi expert. I’d asked to chat with him to discuss strategies for another game I’m working on, called Echo Protocol. He suggested some experiments he could help me run, but noted that these experiments might not work and that I might want to start with a smaller project that I was less worried about ending in failure.
Thus, I combined my love of spaceships, pixel art, and doing everything onchain — whether or not it’s sane — to make WarpFlow.
The result is a collection of WYSIWYG spaceships:
Press enter or click to view image in full size
Onchain Ship Names
I began with a side-quest to ensure that I could give real warship names to each NFT in the collection. Luckily, I already had most of the pieces in place for the contracts themselves with the Onchain Names project I’d built for Echo Protocol.
I just needed to get the ship names themselves. Unfortunately, unlike human first and last names, I couldn’t find an open-source list of names. Luckily, ChatGPT was able to help me find and modify a script to (following the TOS) scrape Wikipedia for ship names by country for the largest 10 or so navies in history. I updated the script for better error handling, skipping already scraped countries, etc.
With AI assistance, I then wrote scripts to dedupe the lists and sort them alphabetically. I then went through probably the most painful part of this project — munging the lists to remove thousands of book, article, and organization names that the scraper grabbed. I also used ChatGPT to help search for and remove as many offensive names as I could, such as a ship in the Italian Navy in WWII named after the Blackshirts. This took more than half a day.
Finally, I added scripts to combine and resort the lists, then turn the final list into json for easy ingestion into the deploy script. This is a modified Hardhat Ignition script that divides the list into subsets, deploys them into individual contracts, then deploys a main contract with the array of subset contract addresses as a constructor argument.
The end result is a set of about 90 static contracts that anyone can use by calling the `randomName` function with a `bytes32` argument. This argument is used to deterministically pick a subset contract, which accepts the `bytes32`, hashes it, uses the hash to pick a name, and passes it back up the chain.
Again, the names are deterministic: `0x6636313932303132383935653232313434333441653944433144353536374675` will always return the name Milne, and through accident, malice, or incompetence, neither I nor anyone else can ever change the list of names.
If I ever need an update, I can always just redeploy the contracts and update the addresses in the contracts that make use of it. Gas on Flow is inexpensive enough that deploying 100 contracts is trivial.
Rendering the Ships
The ships for the upcoming game are randomly generated, selecting their stats and equipment. Higher stats or better equipment do not necessarily improve the value of the NFT, because they take up more of your limited points allotment in the upcoming game the better they are. Instead, value is a combination of the utility of the individual ships stats within your fleet design.
However, ships do become cheaper the more experienced they are — experience gained by destroying other ships. They also start with a randomly selected amount of experience, with higher values being much rarer.
To get these ships fully onchain I used an “octopus” of rendering contracts, each containing SVG art for the portion of ship art corresponding to each property the ships contain.
For example, the accuracy skill is represented by which Fore, or bridge art the ship possesses. When the ERC721 `tokenURI` function is called, it doesn’t return an IPFS link with json metadata. Instead, it calls the contract responsible for assembling and rendering the json metadata based on the data in the ship passed as an argument. That contract in turn calls the Image Renderer, which calls individual contracts to select and return the art for each segment of the ship and its equipment, then assembles the snippets into a full SVG, converts that SVG into base64, and returns it.
Press enter or click to view image in full size
Conclusion
WarpFlow is the result of a weird mix of interests — pixel art, spaceships, onchain maximalism — and a simple suggestion: “Maybe start smaller.” It was fun to build. From scraping and cleaning thousands of ship names to designing a rendering system that assembles SVGs from a web of contracts, WarpFlow was a chance to explore what’s possible when you lean all the way in on-chain.
Check out the repo here: https://github.com/briandoyle81/warpflow-contracts
Browse the latest iteration on testnet Opensea: https://testnets.opensea.io/collection/warpflow-ships-17
I don’t have a frontend yet, but you can play with getting your own ships on FlowScan: https://evm-testnet.flowscan.io/address/0x9e99fb7d6fb06c1c2d5defedf7a6d5e9e73f32de?tab=read_write_contract
Step 1: Get testnet funds from the faucet — https://faucet.flow.com/fund-account
Step 2: Call purchaseWithFlow. The faucet gives you thousands of tokens, so you can buy the top tier and get 125 ships for 99 testnet Flow. Note: This is tier 4 and 99990000000000000000 Flow. Use your own address for recipient and referral.
Step 3: Call constructAllMyShips. Note: Gas limits mean this will fail if you have more than 130 or so ships. If that happens, you’ll have to construct them in groups using the other functions.
Step 4: Check out the ships on testnet OpenSea under your account address!
Remember, these are testnet NFTs, so apologies in advance if you get something really cool — it sadly can’t be migrated to the production version of this collection.