Cointime

Download App
iOS & Android

Creating, Destroying, and Restoring On-Chain Artwork

From Etherscan Blog by Takens Theorem

This post is about an amazing NFT project on Ethereum called “Rothko on Pennies” and the events surrounding it — including my own participation. This project and its provocations illustrate that the artistic character of a project goes well beyond just the instant glimpse of its visual form. On public blockchain, where code is (or, might be) “law,” artwork can solicit interventions, extensions, hacking. A work’s meaning evolves sometimes in surprising ways even to the original creator. And on blockchain that meaning takes technically curious forms, even using tools typically reserved for more malicious intents but deployed for better purposes: hacking art, hacking as art.

“Rothko on Pennies”

The artist Yigit Duman recently created “Rothko on Pennies” (RoP). It is a clever, playful hack of a sort: RoP encodes a rendition of Mark Rothko’s “Composition (1959)” by storing a PNG on tiny balances across almost 1,000 contracts (981 to be precise).

Rothko on Pennies by Yigit Duman, original (unaltered) version

There’s something beautiful in Yigit’s exercise. It’s most certainly a kind of exploit itself. RoP uses a clever trick to get around the strict computational limits of Ethereum mainnet. For one, Yigit exploits the precision of balances to store data (each wei is 1/10¹⁸ ether). He also uses simple balance calls across these 1,000 contracts to reconstruct the image. The balances cost mere pennies, and deploying the contracts cost less than 0.1 ETH in total (about $250 at the time of writing). Yigit’s beautiful NFT project loops through an array of contract addresses, gets their balances, and assembles a base64-encoded payload that shows the Rothko on the token’s metadata.

Yigit Duman encoded data across tiny balances on about a thousand contracts. From Etherscan.

Yigit Duman’s announcement about RoP sparked a lot of attention. Many recognized striking cleverness of the approach: a beautiful rendering of influential abstract artwork stored entirely on-chain across the dust of a thousand contracts. RoP was auctioned for 1.256 ETH, won by Serc.

But there’s a problem. Several recognized the issue right away: Contract balances can be updated, changed.

Yigit observed this issue himself. Indeed, it was by design. You change the balances (the image data!), you change the piece. He playfully taunted his audience to vandalize the artwork. The artist beckons for another performance.

Vandalizing a Rothko

I decided to vandalize the Rothko. At least, to try.

How? You can’t just send ether to Yigit’s contracts to change the balance. It’ll generate an error because these thousand little contracts don’t have a way to handle value sent to them. But there’s a trick. It’s a known vulnerability of Ethereum contracts sometimes called “force feeding.” Basically, you deploy a contract, give it some wei, then trigger that contract to selfdestruct¹ — and instruct it to send its wei to another address, the “victim.” The victim here can be any of the RoP contracts. And by disrupting RoP’s little contract balances, you disrupt the whole piece.

Fun history: This vulnerability was one of a bunch discussed in the “Mastering Ethereum” book by Antonopoulos and Wood years ago. It was fun to revisit these passages in the book, which I own and love, and see early discussion about how this is typically perceived as a potential attack surface for a hack:

You can check out this classic book’s contents here

So I could change the balances, but I didn’t want to destroy the piece. That would be easy. The vast majority of alterations to the balances would just destroy it. Instead I wanted to modify it and leave a visible alteration. To do this I found just a single byte change in the PNG that would render the image asset with a scratch. I used Etherscan’s list of Yigit’s contracts (along with some test code) to determine where and how I needed to target it.

Locationof byte change in the PNG’s encoding.

I could calculate the exact wei needed to change that one contract’s balance and how it expressed that one particular byte: a scratch from a byte. I deployed my contracts, sent the wei using force feeding, and refreshed. Rothko was scratched.

OpenSea’s listing for the RoP.

Destroying a Rothko

I’ll confess being quite proud of this little endeavor. Most of my time was spent choosing a viable target in the bytes expressed by RoP’s balances — like a viable genetic mutation introduced in some long stretch of DNA.

But before long, just hours later, an artist with a penchant for destruction descended upon the RoP. The great destroyer, Bushi, sent a single wei (1/10¹⁸ ether) to another contract and destroyed the entire piece. Obliterated. Bushi sent a message along with the selfdestruct transaction: “all good things must come to an end.”

From Bushi’s 1 wei selfdestruct transaction. From Etherscan.

It was a suitable event. The piece seemed designed with a playful destruction in mind. And Bushi was the best culprit, known for artworks that are at once innovative and destructive in their nature.

From Yigit Duman’s beautiful RoP summary site.

Artist Yigit Duman seemed to celebrate this, and wondered if it could be restored. Another challenge. I’ll confess spending several hours fiddling with possibilities. I imagined updating balances to simply alter the artwork again and recover some of it. I succeeded in part. I tried to send another transaction, to overcome Bushi’s destructive 1 wei. It didn’t work: Other vandals had already modified some of the other 1,000 contracts.

Fully Restoring a Rothko

I inspected Yigit Duman’s rendering code closely. This is the code that takes the balance values (expressed as large integers of how much wei is in each balance) and assembles the image. It occurred to me that he was using a smaller integer type (uint40) when rendering the balances.

From Etherscan: Yigit Duman’s RoP rendering code.

Integer typing is subject to another very well-known vulnerability, often used as an attack surface too: I can overflow this integer type and force Yigit’s rendering contracts to “think” it’s back to the same original number. The idea can be visualized like this:

When the integer reaches its max, it “loops back” onto 0. Visual from here.

This attack vector has history too. Early in Ethereum’s history, it was used as an exploit on some ERC-20 token projects, which you can read about here. (Wood and Antonopoulos also discussed over- and underflow issues in their list of vulnerabilities.)

Anyway, I needed to take several steps before making this happen. (I share lots of detail in this elaborate thread here.) First, I assembled some test contracts replicating Yigit’s contract environment to make sure it would work. Also key was using Etherscan’s API to scan for both the addresses and the balances of RoP’s contracts. By detecting which of the RoP contracts had “internal transactions” (those selfdestruct events) I could tell that several had been sent some wei:

Data extracted from Etherscan’s API using internal transaction type.

But it was doable. Using data and these tools I calculated for each contract how much wei I’d need to overflow the uint40 operation and “loop back” onto the original values. I did it for all the attacks on RoP except for one: I did not reverse my scratch.

I sent the transactions. A few moments later, I refreshed the amazing On-Chain Checker platform that calls data from the contract directly. The pixelated on-chain rendering of Rothko’s red glowed on the screen, the scratch still there. A moment of sheer delight.

Visit the current RoP state here.

(Collective) Hacking (as) (Performance) Art

There are many amazing things about Yigit’s RoP project. From a very concrete perspective, working with the puzzle Yigit set required a dizzying combo of various tools and techniques — the Etherscan-derived data about contracts and their balances, the byte-level definition of images, Solidity hacks to manipulate a project under the rules the project sets for itself. Yigit’s project is technically impressive right away — ether dust encodes a Rothko. But that’s only the surface — RoP sets a challenge to the familiar and inclined and the project itself proliferates into new and fun complications.

But the semantic qualities of Yigit’s work go well beyond the technically impressive feature of RoP’s initial trick. It is emblematic of cryptoart, especially on-chain cryptoart. On a public blockchain, those who can are invited to engage, to interact, to code and hack and participate and alter the meaning of a piece.² Yigit, Bushi and I (and possibly some other vandals) converged on a decentralized ledger and wrangled a work of art. We acted remotely in space and time engaging in computable, permissionless, unstoppable play.

Epilogue

I corresponded with Yigit Duman about RoP, and he shared some final remarks about the project and what inspired it:

Rothko on Pennies was an incredibly rewarding exploration of Ethereum as an artistic canvas. Takens Theorem’s work, along with the element of ‘vandalization,’ elevated the entire narrative, showcasing the potential of multiplayer interactive art on Ethereum. I’ve long been inspired by the pioneering artists in the on-chain art space, and with this project, I hope to have sparked some inspiration in others.

Though the official performance is complete, RoP remains forever open for engagement. Indeed it was vandalized again, several times, to the point of destruction. So I repaired it again (this time, by devising a generic solution). The chain is forever and often daunting in its latent potential.

Endnotes

  1. This use of selfdestruct may be retired in the near future, as Yigit discussed in another thread during these escapades.
  2. There are various stationed art traditions that have this quality too. There are many well-known examples of participatory conceptual art, computer art, etc. I do not review these here for simplicity, but you can consult an interesting review here of some ideas.

Disclosure

I sometimes own or create projects I mention. I was not paid for this post. I wrote it for fun. Thanks to Etherscan for letting me contribute. You can find me on X with links to projects here:

https://www.takens.eth.limo

Comments

All Comments

Recommended for you