Ethereum – Art Market

Here is a contract that allows you to register as the owner of a digital artwork contained in a particular file (identified by its cryptographic hash value) at a particular URL. The use of a URL is inspired by the excellent Monegraph, which launched shortly after I started working on Ethereum contracts for art. Monegraph uses the existing NameCoin system, which can be implemented in Ethereum as a two line contract.

This contract is longer than that as it’s recording and managing more information. It also allows you to offer the artwork for sale (in exchange for Ether, Ethereum’s built-in currency), either to a specific individual or generally, or to transfer it to a specific individual without charging them within the contract.

{
 (def 'next-record 0x10)
 (def 'RECORD-SIZE 64)
 ;; Next record position
 ;; This starts one cell above the maximum value of RipeMD
 [[next-record]] 0x10000000000000000000000000000000000000000

 (return
   0x0
   (lll
     {
      ;; Action
      ;; 0 - first cell in message
      [action] (calldataload 0)
      (when (= @action "register")
        {
         ;;TODO: Check correct message length
         ;;TODO: Check digest in range
         ;; Artwork digest
         [digest] (calldataload 32)
         ;; If already registered, don't continue
         (when @@ @digest
           (return "Arwork already registered."))
         ;; Get storage for new record
         [storage] @@next-record
         ;; Store digest
         [[@storage]] @digest
         ;; Artist account
         [storage] (+ @storage 1)
         [[@storage]] (caller)
         ;; Artist resale percentage
         [storage] (+ @storage 1)
         [[@storage]] (calldataload 64)
         ;; Artist is the current owner
         [storage] (+ @storage 1)
         [[@storage]] (caller)
         ;; Skip purchaser and price
         [storage] (+ @storage 3)
         ;; Copy over the url and description
         ;; 96 is 32 x 3 = 3rd cell in message
         [source] 96
         (for [i] 6    (< @i 64)    [i] (+ @i 1)
              {
               [[@storage]] (calldataload @source)
               [storage] (+ @storage 1)
               [source] (+ @source 32)
               })
         ;; Store digest-to-record link
         [[@digest]] @@next-record
         ;; Increment next record position
         [[next-record]] (+ @@next-record RECORD-SIZE)
         })
      (when (= @action "offer")
        {
         ;;TODO: Check correct message length
         ;;TODO: Check digest in range
         ;; Get artwork record storage for digest or stop
         ;; 32 = second cell in message
         [storage] @@(calldataload 32)
         (when (not @storage)
           (return "Artwork not registered."))
         ;; If the caller is the owner
         (when (= @@ (+ @storage 3) (caller))
           {
            ;; Offer subject
            [[(+ @storage 4)]] (calldataload 64)
            ;; Offer price
            [[(+ @storage 5)]] (calldataload 96)
            })
         })
      (when (= @action "accept")
        {
         ;;TODO: Check correct message length
         ;;TODO: Check digest in range
         ;;TODO: Error messages for bad price or buyer
         ;; Get artwork record storage for digest or stop
         ;; 32 = second cell in message
         [storage] @@(calldataload 32)
         (when (not @storage)
           (return "Artwork not registered."))
         [buyer] @@(+ @storage 4)
         [price] @@(+ @storage 5)
         ;; If the caller is the buyer and it's the correct payment
         ;; Or there's no buyer and it's the correct nonzero payment
         (when (|| (&& (= @buyer (caller))
                       (= @price (callvalue)))
                   (&& (= @buyer 0)
                       (> @price 0)))
           {
            ;; For payment
            ;; Ethereum doesn't allow fractional amounts
            ;; Warn users about making prices divisible
            [hundredth] (/ @price 100)
            [arr] @@(+ @storage 2)
            ;; Pay artist
            (call (- (gas) 250) @@(+ @storage 1) (* @hundredth @arr) 0 0 0 0)
            ;; Pay owner
            (call (- (gas) 250) @@(+ @storage 3) (* @hundredth (- 100 @arr)) 0 0 0 0)
            ;; Transfer ownership
            [[(+ @storage 3)]] (caller)
            ;; Clear offer subject and price
            [[(+ @storage 4)]] 0
            [[(+ @storage 5)]] 0
            })
         })
      }
     0x0))}

Here’s the top and the bottom of the main UI (implemented in HTML and JavaScript for the AlethZero Ethereum client).

registry1
registry3
You can enter a URL and get the cryptographic hash for it.

registry2
If the artwork has already been registered, this will show its details.

registry5
Or if not you can register it.

registry4
Once you’ve registered an artwork you are the artist of it and you also own it. You can offer any artwork you own for sale.

registry6
And you can accept a sale offer, paying the specified amount of Ether.

registry7
The UI warns you how much Ether you are about to spend.

registry8
And when you buy an artwork it lets you know when the transfer is complete.

registry9
It’s a market in allographic digital art. In contrast to the existing art market it is entirely public and transparent. And in contrast to many jurisdictions it implements the controversial “Artist’s Resale Right” in a voluntary way (in a way similar to that suggested in “The Social Lives of Artistic Property“). If it’s prohibitively difficult to experiment in the existing art market, we can make new markets for new kinds of art. Like this one.

Ethereum – Art Is…

Here is a contract that allows anyone to define what art is. It contains a single set of twelve statements about art. They are encoded as hexadecimal values which are interpreted as sentences in a simple subset of International Art English and displayed by the UI.

{
 ;; Constant values
 ;; Price base (wei), doubled for each definition up to DEFS-COUNT
 (def 'PRICE-BASE 10)
 ;; Add to the index to get the price base exponent
 (def 'PRICE-FACTOR-ADD 10)
 ;; Number of definitions
 (def 'DEFS-COUNT 12)
 ;; Range of values for definitions
 (def 'DEF-MIN 0x1)
 (def 'DEF-MAX 0x0F0F0F0F)

 ;; Storage locations
 (def 'artist 0x10)
 (def 'defs-base 0x100)
 (def 'theorists-base 0x200)

 ;; State
 ;; Contract owner/payee
 [[artist]] (caller)

 (return
   0x0
   (lll
     {
     [action] (calldataload 0)
      (when (= @action "set")
        {
         [index] (calldataload 32)
         [definition] (calldataload 64)
         [price] (exp PRICE-BASE (+ @index 1 PRICE-FACTOR-ADD))
         ;; If the index is in range and the caller paid enough to set it
         (when (&& (>= @definition DEF-MIN)
                   (<= @definition DEF-MAX)
                   (< @index DEFS-COUNT)
                   (= (callvalue) @price))
           {
            ;; Update definition
            [[(+ defs-base @index)]] @definition
            [[(+ theorists-base @index)]] (caller)
            (- (gas) 100) @@artist @price 0 0 0 0
            })
         })
      }
     0x0))
 }

The contract is in lll rather than Serpent this time.

Here’s what the UI looks like.
art_is1
And here’s what it looks like when a statement is being edited.
is_art2
The contract allows the statements to be edited but it costs progressively more to do so: the first costs 10 Wei, the third costs 1000 and so on. This ensures that art theorists place a value on their definition, thereby indicating how confident in and/or serious about their definition they are. The higher the value, the less likely it is to be changed by someone else. This combines art theory with behavioral economics.

Ethereum – This Contract Is Art

Here is a contract that can assert that it is art.

init:
    contract.storage[1000] = "may be"

code:
    if msg.data[0] == "toggle":
        if contract.storage[1000] == "is":
            contract.storage[1000] = "is not"
        else:
            contract.storage[1000] = "is"

It toggles its status as art when sent a message instructing it to do so.

Here’s what the UI for the contract looks like:

is1

Here it is while the artistic state of the contract is being toggled:

is2

And here it is after being toggled:
is3
Anyone can change the contract from not being art to being art (and vice versa). We’ll look at a more advanced contract that uses behavioural economics to address this next.