Smart Contracts in Ethereum, Solidity, and Geth: first impression

Today is another exciting day, because I was able to build and deploy a simple smart contract on the Ethereum production chain.

What is a smart contract? A contract that is signed and executed digitally, between one or several parties. For example, a Zipcar rental can be described as a smart contract, since all steps from booking to unlocking, to returning the car are automated. A traditional car rental is not a smart contract, since it requires me to sign several papers and the counter person to physically give me the key to the car.

What about distributed smart contracts? They are smart contracts that can be signed and enforced via a decentralized network - so unlike the Zipcar rental, they may not require a corporation intermediary.

Why are distributed smart contracts important? Because much of modern economy is, in the end, about creating, documenting, settling, and litigating contracts, in a very centralized way. Smart contracts can remove the layer of intermediaries, so that people and companies can transact directly with each other. In the future, the smart contracts may even replace lawyers with coders, or have coders go to law school, or have lawyers learn how to code, whichever is easier. Of course, the application of blockchain is not limited to financial services - healthcare and governance projects are also being implemented.

Initial impression

Ethereum is still in early stages of development, and it is impressive what the team has accomplished to date. The blockchain is the first public one that actually permits execution of smart contracts, and the software is mostly easy to use. And all of this was crowd-funded by the sale of ether, the chain's cryptocurrency.

Ethereum and smart contracts are very different from the old-school coding - smart contracts are asynchronous. A "transaction" sent to a contract can take a minute to process and get "mined" - in the meanwhile, the contract remains in the old state. This is the cost of confirming the transaction by a consensus of mining nodes: we cannot be 100% sure a transaction has completed until it enters the main chain. In some instances, a transaction may end up on an orphaned block and then it will not be reflected in the state variables of the contract.

In practice, this considerable latency can be a barrier for fast retail transactions (image settling a restaurant bill!), but should not be a problem for deals where a few minutes' settlement is acceptable, or for person-to-person money transfers.

Technical steps

First and foremost, one needs a Ubuntu Linux computer. I used the digitalocean virtual box, which costs $10/month. This second-cheapest option, however, is barely sufficient to run the full Ethereum client. At this time, the 30GB of disk space is 90% full. On this computer, I installed the Geth Ethereum client. The steps for the installation can be found on Github - but be prepared to spend a couple of hours downloading dependencies. 

When Geth starts for the first time, it will set up an Ethereum account with a passphrase. The passphrase must be saved securely, or else all funds in the account will be lost.

Secondly, I needed Ether to deploy and run the contract. I started by buying Bitcoins on Circle. Then I swapped them for Ether on Shapeshift, using my new Ledger wallet as the source of funds. So the account managed by Geth was now populated.


Finally, my full client needed to synchronize with the blockchain. A great idea is to have Geth run in the background, because it will take several hours for the client to synchronize, and the state database to download. A great reference is here: https://hiddentao.com/archives/2016/05/04/setting-up-geth-ethereum-node-to-run-automatically-on-ubuntu/. Then the interactive geth can be started with 'geth attach'.

The code that I executed can be seen below. It creates a Messenger contract, where anybody can send a message, and anybody can read it. This 'contract' is extremely simplified on purpose, because in the Ethereum world, each increase in complexity takes several hours or days to go through. In my next experiment, I will implement a multi-party contract with conditional payments.

The resulting contract can be seen at the following address: http://etherscan.io/address/0xe9b57fd6c767893b0fa5de7206fb2917e748bcb1

Code

Geth is an interactive Javascript shell. To deploy the contract, I entered the following commands in the shell. One key point about the code is the amount of gas specified in the deployment command. I used the online Solidity compiler on Github to check that amount. Too little gas will get the contract rejected, and too much gas is wasteful, because it will be collected from my Ether money.

var contractSource = 'contract Messenger {

    string message;
    address owner;

    function Messenger() {
        owner = msg.sender;
        message = "";
    }

    function kill() { if (msg.sender == owner) selfdestruct(owner);}

    function SendMessage(string message_) {
        message = message_;
    }
    
    function ReceiveMessage() constant returns (string)
    {
        return message;
    }
}';

var contractCompiled = web3.eth.compile.solidity(contractSource);

var myContract = web3.eth.contract(contractCompiled.Messenger.info.abiDefinition);

web3.eth.defaultAccount = web3.eth.accounts[0];

personal.unlockAccount(web3.eth.defaultAccount);

var messenger = myContract.new({from:web3.eth.accounts[0], data: contractCompiled.Messenger.code, gas: 309425}, function(e, contract){
    if(!e) {

      if(!contract.address) {
        console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined...");

      } else {
        console.log("Contract mined! Address: " + contract.address);
        console.log(contract);
      }

    } else {
        console.log("e is true");
        console.log(e);
    }
})

personal.unlockAccount(web3.eth.defaultAccount);


messenger.SendMessage("Monkey");

messenger.ReceiveMessage();

personal.unlockAccount(web3.eth.defaultAccount);

messenger.SendMessage("Orangutan")

messenger.ReceiveMessage();

personal.unlockAccount(web3.eth.defaultAccount);

messenger.kill();

Result

The contract results can be seen here:

http://etherscan.io/address/0xe9b57fd6c767893b0fa5de7206fb2917e748bcb1

Screenshots






Comments

Popular posts from this blog

A smart collateralized non-recourse futures contract on Ethereum: first impression

Ethereum Client Platforms: Parity versus Go-Ethereum

How to steal money in Ethereum (and how to protect your Ether)