Thought it’d be fun to explore blockchain hype and write a simple Ethereum smart contract based on an short story from the 19th century.

In middle school, I remember reading Robert Louis Stevenson’s The Bottle Imp, written in 1891. The story describes the the struggles of a person who buys a magic bottle from an elderly man who lives in a “fine house on a hill” in San Francisco. It grants unlimited wishes with certain evil conditions: you can’t sell it to anyone else for more than you paid for it and if you can’t find a willing buyer before you expire you’re doomed. You also have to pay in real minted coins: no paper money is allowed so there’s some physical limit to how cheaply you can sell it.

Remembering this story while reading about the blockchain, the obvious thing to do was attempt to implement it as an Ethereum smart contract on a sunny Sunday afternoon. I’ve published the code on Github here.

My attempt at sounding like I know about what I’m talking about about with blockchain

This was my first attempt and building a ÐApp (decentralized app). I feel like including this diagram of distributed networks from a 1962 academic paper gives this post some additional gravitas and is completely self-explanatory on the benefits of decentralized applications, the nature of distributed ledgers, and inherent security considerations of applications built using this technology:

On Distributed Communications Networks, Paul Baran (1962)

Now that we have a full and complete understanding of Ethereum and distributed applications, how does the contract work?

As for why I sell so cheap, I must explain to you there is a peculiarity about the bottle.

— The Bottle Imp

In the process of writing this smart contract, I was terrified. Outside of the usual pains of figuring out how to write, deploy, and build things using a completely new toolchain (the Solidity language, testrpc, and the web3 APIs), it was unsettling to read though a popular resource on potential security vulnerabilities from ConsenSys.

The contract I wrote (my first) does only one trivial thing by design: transfer ownership of the (virtual) bottle if they pay less than the previous owner.

However, from best practices I found it seems clear that production-grade smart contracts need to go through a lot of testing and analysis. Specifically, it’s a good idea to:

Really understand the Solidity language and know the danger of external calls, transfer calls, and reentrancy vulnerabilities.

Integrate rate-limiting and “pause” functionality if things go wrong.

Use static analysis and linting to catch vulnerabilities.

Explore different patterns to upgrade your contract as new vulnerabilities are discovered.

Start a bug bounty program to thoroughly test it (with rewards to those who find issues) before the contract goes live on the main ethereum network. Maybe hire some consultants for auditing purposes, too (they were all over my Google search results for Solidity development questions).

Consider using frameworks like truffle or OpenZepplin when you realize you’re probably doing it wrong.

Attempting to, uh, “implement” some of those best practices over a couple hours, I came up with this code for the key logic in the contract to transfer the bottle. If the price is less than the price the previous owner paid and it’s non transferred back to the same account— the bottle has a new owner and the price paid is transferred back the previous owner:

function buyBottle() payable public {

// Conditions

require(msg.sender != currentOwner);

require(msg.value > 0);

require(msg.value < lastPricePaid); // Effects

previousOwner = currentOwner;

currentOwner = msg.sender;

lastPricePaid = msg.value;

LogTransfer(previousOwner, currentOwner, lastPricePaid); // Interactions

// *Security alert (correction on October 27, 2017):*

// This implementation isn't safe! See GitHub and comments.

previousOwner.transfer(msg.value);

}

The “conditions”, “effects” and “interactions” comments are only for reassurance based on a solidity question I read on StackOverflow. Otherwise, I’m conservatively ~40% sure it works without a major structural flaw or security vulnerability.

Like the original short story, there’s ultimately a loser in this contract: if the value paid is 1 wei — the smallest allowable unit in Ethereum, you’re stuck with ownership of this smart contract forever.

After some local testing and trying it out on the Rinkeby test network, decided it was time to ship it.

It’s live on the main Ethereum network, beware!

“This is the bottle,” said the man; and, when Keawe laughed, “You do not believe me?” he added. “Try, then, for yourself. See if you can break it.”

— The Bottle Imp

The contract/virtual bottle has been published to the main Ethereum network and is able to be transferred to anyone who wants it— as long as you pay less than the previous account did. I’m curious to see how long it takes for the value to get down to 1 wei and what happens (if anything).

To kick things off, I’ve started the price of the contract at the going rate of a of a typical sandwich in the Financial District of San Francisco: 0.05 ETH (~16 USD).

If you’re new to Ethereum, I’d recommend downloading the Mist browser or Metamask extension and then visiting the following address: https://wallet.ethereum.org/account/0x9fcd683584173c5df0ee47852f5592f68ed72a0c

The contract visualized in the Mist browser. The “buy bottle” function transfers ownership.

Feedback and vulnerability assessments welcome in the comments, on twitter, or on the Github project page.

If you’re new to all this can also recommend Coinbase’s general introduction to Ethereum (and how it’s different from Bitcoin). For getting started with development, the Reddit community was useful too.

Regardless of where the blockchain hype goes — and who ends up stuck with the smart contract I created when they buy inevitably buy it for 1 wei — it was really interesting to learn more about the process of building and testing smart contracts. Last word, as it does in The Bottle Imp, goes to the boatswain: