Play L2 Games with L1 Assets

I’ve spent the last few months building Wrasslers, a blockchain-based battling game for NFT avatar projects that’s designed to be open and permissionless. While most web3 games are constructed as vertically-integrated walled gardens, the vision for Wrasslers is to allow anyone to create NFTs that conform to an open-source Wrassleable standard. Any NFT developer can craft assets (or wrap existing ones) for compatibility with the Wrasslers on-chain fighting game, and other game developers can build new or competing experiences that utilize the same standard. I’m seeking positive sum outcomes, where the Wrassleable standard, compatible tokens, Wrasslers itself and other on-chain games all become more valuable by being composable NFT LEGOs.

I’m passionate about digital asset portability and envision a world where the digital assets we own move around with us as we enter and exit various interconnected metaverse experiences. Your wallet of NFTs is your inventory for the metaverse — an uncontroversial yet unexamined maxim among web3 champions. I want to own an NFT car and use it in any racing game, and as transportation in virtual worlds. I want to do this no matter who the NFT automaker is, no matter who makes the games or the virtual worlds. We can avoid cold start problems, allowing new games and experiences to bootstrap their worlds with assets a user already owns. We won’t have to stick around dying worlds for some notion of sunk cost, so developers will need to continue to innovate and delight to keep users coming back. And we’ll open up this new world economy to the long-tail of creators - every time a metaverse experience creates a one-off partnership with a leading NFT project or legacy brand, we add another brick to the wall of the garden, replicating winner-take-all Web 2.0 outcomes.

There are two challenges we need to collectively solve to ensure we get the open metaverse we deserve. The first is philosophical in nature - how do we begin to layer meaning or capabilities or properties into digital assets in the most useful way? How can we start to find and codify the edges of these essential aspects of an object in a way that is bottoms up and accessible to all? How do we move from pictures of things to actual things - NFT cum object?

0xEssential will champion open-source standards for object ontology, for adding meaning and capability to digital assets. Most Solidity developers inherit battle-tested contracts from Open Zeppelin’s NPM package to add the standard functionality for the ERC721 spec. 0xEssential may offer an SDK with inheritable contracts that provide meaning or capability, something like Platonic Forms. Adding meaning to tokens can be as simple as inheriting a contract or series of contracts that best describe your item’s essential nature: contract MyNFT is ERC721, Ownable, Automobile, Raceable, Fuelable, Wreckable {…}. Perhaps the better solution will be to wrap or annotate NFTs on-chain, or use something like DIDs or creating a new layer, a layer for meaning.

The other challenge is more technical, but the driving factors for how best to solve this challenge must be user and developer experience. We’re living in a multichain world. And while I can appreciate I’m new to the space and perhaps naive, I am not convinced that bridging NFTs all over the place is an acceptable user experience for playing games. Expensive, slow and perhaps unnecessary.

And so I’ve been experimenting with different approaches to solve these challenges — how can we attach meaning or capability to new and existing digital assets? Can we somehow keep those assets on Layer 1, and use them in games with smart contracts deployed someplace else? What tradeoffs must we make to solve these challenges, and are they acceptable? Can we iterate towards a solution that meets all of our goals, that makes integration easy for NFT and metaverse developers, while remaining true to a decentralized ethos?

Derivative Layer 2 Tokens

The first approach I built for the Wrasslers alpha release to solve capability and cross-chain challenges was to mint derivative tokens on Polygon. User visits dapp, we load all the Layer 1 NFTs they own, and allow the user to select a token and sign a message. We submit that signed message to our own API layer, where we use a JSON RPC to verify that the address does in fact own that NFT and to fetch its metadata. We then submit a transaction to Polygon to mint a new derivative NFT that includes Wrassleable. The Wrasslers gaming contracts on Polygon could interact directly with the Wrassler’s NFT contract on where we minted derivatives for our players.

This worked well-enough - we saw a few hundred addresses mint a derivative and play 500+ matches. But the derivate NFT Alpha Wrasslers collection we created on Polygon was delisted from OpenSea, presumably due to IP infringement. And it’s not a great user experience either to have 2 nearly identical tokens existing on different chains. It feels counter to what I think we want when we consider the possibility of blockchain gaming without bridges. If an address were to sell or transfer the L1 token, they’d still have the L2 token and could continue to play with it, a confusing outcome especially if the L1 holder also starts playing Wrasslers.

Loot NFT Integration

I later integrated Loot project into Wrasslers using the same sort of approach - signed message and some centralized web server logic before submitting a transaction to Polygon. I wanted to give players free attribute upgrades based on the rarity of the items in their bags. There’s quite a bit of logic in this API route, which I think is some evidence that we also really do need to solve the first challenge - Loot is so interpretable it is almost meaningless, and the entire burden of “what does this mean for my game” is placed on me, the game or metaverse developer. If we continue down that path, importing users’ existing assets is more work for metaverse or game developers than it is to create their own vertically-integrated items. We need to make it easy and positive sum for metaverse developers to integrate the assets you already own, or else they simply wont.

Once I had integrated Loot, I realized that I now had a second approach for using L1 assets in the L2 contract that didn’t require minting a derivative. I also knew I wanted to implement meta-transactions; Wrasslers is an onchain game, and $MATIC is the gas token on Polygon, which can be a bit of a pain to get. And sure, $0.04 USD is acceptable for me to pay to take a turn, but it’s maybe not feasible for players in other parts of the world.

So I decided to see if I could get two birds stoned at once - cover transaction costs while also removing the need to mint derivative tokens. What I came up with is an approach I’m calling Meta-Transaction Middleware. I decided to migrate the meta-transactions from my own infrastructure onto OpenZeppelin Defender for additional security, and rather than minting derivatives, use current Layer 1 ownership data checks as an authorization mechanism in between the dapp and the Layer 2 contracts.

Meta-Transaction Middleware

Our game contract is on Polygon - we really do not need the security of Ethereum for a game like this. But it would also be absolutely insane to bridge your CryptoPunk to Polygon to play Wrasslers from a security, cost, user experience and timeliness perspective.

So the goal is to allow a user to play a Layer 2 game with an NFT they own on Layer 1. A nice win is that we will also pay gas for the moves - it’s inexpensive, and we improve UX by not forcing the user to switch networks in their wallet or having to figure out how to get $MATIC on Polygon.

The flow for meta-transactions generally looks like this. A user signs transaction parameters with their wallet and submits the signature via HTTP off-chain. A web server then receives that request, validates it, and submits an on-chain transaction with the signature. This transaction is sent to a special contract that accepts the signature, appends it with the signer address, and forwards to the implementation contract that understands how to read the signer address to establish caller context.

via OpenZeppelin https://drive.google.com/file/d/1C3Oo2G5lCZlkdcDuiHodMr5jXRt98qFZ/edit
via OpenZeppelin https://drive.google.com/file/d/1C3Oo2G5lCZlkdcDuiHodMr5jXRt98qFZ/edit

There are various options for adding meta transaction support to your project. You can use my naive attempt and submit transactions from a gas wallet on your own API. There are services like Biconomy that make it simple to add this functionality yet don’t give you much control on the verification step. We need full control over the verification step to run our Layer 1 ownership check, and Open Zeppelin Autotasks feels like the goldilocks solution - a lambda-like environment with a full NodeJS runtime that offers more security and reliability than submitting transactions from your own API.

Without getting too technical, the pink circle is where we do our magic! While our Autotask is set up to submit transactions to Polygon, it also allows us to write code that can make read calls to Ethereum Layer 1 through an RPC endpoint from a service like Infura. We use this capability to do just that - we always include the contract address and token ID of the NFT a user wants to use in a game move in the signed message, and then unpack it all and ensure the signer does in fact own that NFT before submitting the transaction to Polygon. The result is a smooth, performant and free game for users, and if we plan to bring more users into web3 we need to focus on these UX improvements.

If we need this authorization check to run before a transaction is submitted, I have to admit that we trade some decentralization for user and developer experience. Our game is still on-chain as game moves and outcomes are recorded on the public ledger. And it still feels permissionless in the sense of allowing gameplay using any Layer 1 NFT. But it’s also true that a user (or bot!) cannot play Wrasslers by calling our smart contracts directly. I do question what the point of this all is - if the smart contract can only be called via a centralized API, why build the game on-chain at all? But I’m an adherent of both iteration and progressive decentralization and would prefer to get this approach into user and developer hands before trying to find perfect the solution.

Alternative and Future Approaches

I’m not the only person thinking about and hacking on ideas like this, particularly as Loot seemed to light a creative fire around similar ideas. It’s been a great joy to learn and hack and innovate alongside other developers building Layer 2 experiences that utilize Loot and its derivative ecosystem.

@geeogi shipped a super elegant solution for Loot NFTs on Polygon, calling it a Loot Mirror. The Loot contract was deployed to Polygon with some minor adjustments to functions related to ownership. What’s really neat about this approach is that the Loot attributes are determined by token ID. So by deploying the same logic, we get the same attribute data on both layers when given a token ID. Instead of using a middleware, the project runs a cron-task that fetches all changed Layer 1 ownership data and submits a transaction to update ownership on Polygon. So this still depends on some centralized code being run, but an interesting aspect is that it’s run as a Github Action, and at least allows anyone to verify the offchain operations. Compared to the middleware approach, this offers the ability to use more decentralized Layer 2 contracts while sacrificing ownership data accuracy.

Despite being committed to iterating towards a final solution, I also cannot get the idea of a permissionless protocol to solve these challenges out of my head. Again, I am perhaps naive and always open to feedback, but I am not convinced bridging NFTs is a feasible solution to support gaming. And so as more developers start building on-chain games with NFTs it starts to feel like Layer 1 ownership data, accessible on other chains or in other contexts, is incredibly valuable public-good data. I’ve put together some code and early thoughts on what this might look like - a Cross Chain Ownership Protocol. The entrypoint is an Ethereum Layer 1 contract that allows anyone to pay the transaction fee for looking up current ownership data of an NFT and broadcasting that to other chains, to a subgraph, to wherever we might find it useful. It’s not dissimilar to the mirror idea, but supports any ERC721 or ERC1155 and can be called on-chain by any address. We can reward these submitters of data with a token, and use that token for governance of the protocol. But that’s where my tokenomics knowledge ends. I know we’d need to provide some liquidity to protocol contributors, but this perceived value of the data needs to turn into actual value at some point for this to make any sense.

Let’s Buidl

As the NFT and blockchain gaming spaces mature I expect we’ll collectively need to solve the challenges I’ve laid out here as well as future challenges we can’t yet know. Wrasslers feels like a toy right now, and I’m committed to building a great game, but it’s incredibly clear to me that we need to solve these challenges of interoperability to ensure we build an open metaverse. And if we don’t solve these challenges quickly, I fear that the Facebooks and Epics and EAs of the world will try to move in and own the metaverse, rejecting the notion of portable assets, of supporting a long tail of creators, of allowing us to move freely with our goods between experiences.

If these goals or challenges resonate with you I’d love to connect! I’d be happy to help other game and metaverse developers implement the meta-transaction middleware I’m experimenting with. And I’d love to hear from folks who might be able to help craft the Cross Chain Ownership Protocol in case we need to get there sooner than later.

You can find me via @sammybauch and I’d love for you to join the 0xEssential Discord.

I’m offering this piece an editioned NFT. I don’t expect anyone to buy it. But it does feel odd that I feel wrong about doing this? As if medium has conditioned me to feel like I should give away my writing for free and for them to benefit from. So I’m experimenting!

Subscribe to sammybauch.eth
Receive the latest updates directly to your inbox.
Verification
This entry has been permanently stored onchain and signed by its creator.