Monday 1 September 2014

Notes on Sydney Ethereum Meetup #1

Not sure how long it will take before the content of this post becomes obsolete, but this is the code I have been using last week (28th Aug 2014) for my demonstration of Ethereum (PoC5).

My demo was mainly a refreshed adaptation of the initial Maran Coin example.
The Mutant code I wanted to have for my contract was:


contract.storage[tx.origin()] = 32000

return compile {
    var to = this.data[0]
    var from = tx.origin()
    var value = this.data[1]

    if contract.storage[from] > value {
        contract.storage[from] = contract.storage[from] - value
        contract.storage[to] = contract.storage[to] + value
    }
}

But I gave up trying to use Ethereal (GUI version of the GO client) due to 25531 block error and the other issues reported on that same forum thread.

So instead, I installed the latest release version of Alethzero (v0.5.17/Darwin/clang/
ee6e07626c9c0aa0e66173e93f0d878c1cd03c7e) running on OSX. I could connect to the Testnet.

Few of us would be comfortable writing a contract in straight LLL.

A convenient solution I found was to use EtherScript. This was also useful for learning what should be the correct syntax in Serpent (which anyway I did not get to use eventually).

The contract can be represented as:



A quick way to obtain it is simply to select the XML representation and copy paste the XML found in: Alexos Coin Etherscript.

The relating Serpent code is automatically generated. It looks like:


init:
  contract.storage[tx.origin] = 32000
code:
  src_address = tx.origin
  src_balance = contract.storage[src_address]
  amount = msg.data[1]
  dst_address = msg.data[0]
  dst_balance = contract.storage[dst_address]
  if src_balance >= amount:
    contract.storage[src_address] = (src_balance - amount)
    contract.storage[dst_address] = (dst_balance + amount)
  else:
    stop

But the code we need to extract from EtherScript is the LLL version of it.
It looks like:


(seq

  (sstore (origin) 32000)
  (return 0 (lll (seq ;; START BODY

  [src_address]:(origin)
  [src_balance]:(sload @src_address)
  [amount]:(calldataload (* 32 1))
  [dst_address]:(calldataload (* 32 0))
  [dst_balance]:(sload @dst_address)
  (if (>= @src_balance @amount)
   (seq
    (sstore @src_address (- @src_balance @amount))
    (sstore @dst_address (+ @dst_balance @amount))
   )
   (seq
    (stop)
   )
  )

  ) 0)) ;; END BODY
)

Ok, so that's the piece of code we can copy from EtherScript and paste into Alethzero, in the Transact Panel:




Had some issues trying to Execute the creation of this contract but it eventually went through (I had to restart AlethZero if I remember correctly).

Note that I have 2 accounts:
  1. cc9ba8b85a38d0f32c4f15c450e9c88170a2e839
  2. 8b5aee50c83a81a644514ccde9c6e66daa90f709
The contract was created on the blockchain (block #44716) using the first account (cc9ba), as illustrated:


Very important: take note of the address of the created contract. Here it is:
0da561f4332778bb5bf289c693f4000748b30080

In order to visualize the balance of AlexosCoins (I think I was calling them JiveCoins in during my demo :) I was using the following HTML page that can be loaded in the central panel of AlethZero:


<html>
  <head>
    <script type="text/javascript">
      function init() {
        var clientAddr = eth.coinbase;
        document.querySelector("#clientAddr").innerHTML = clientAddr;
        
        var contractAddr = "0x0da561f4332778bb5bf289c693f4000748b30080";
        var alethEtherBalance = eth.balanceAt(clientAddr).dec();
        document.querySelector("#alethEtherBalance").innerHTML = (alethEtherBalance / Math.pow(10, 18)) + " eth";

        var alexosBalance = eth.storageAt(contractAddr, clientAddr);
        document.querySelector("#alexosBalance").innerHTML = alexosBalance.dec() + " Alexos";
        
        document.querySelector('#sendCoins').onclick =
            function() {
                var destAddr = ("0x" + document.querySelector("#receiver").value).pad(32);
                var amount = document.querySelector("#amount").value.pad(32);
                var data = (destAddr + amount).unbin();
                document.querySelector("#data").innerHTML = data;
                
                var res = eth.doTransact(eth.key, 0, contractAddr, data, "100", "10000000000001");
            };
      }
      
      window.onload = init;
    </script>
  </head>
  
  <body>
    <h4>You are logged as:</h4>
    <div id="clientAddr"></div>
    <h4>Your Ethereum balance is:</h4>
    <div id="alethEtherBalance"></div>
    <h4>Your Alexos balance is:</h4>
    <div id="alexosBalance"></div>
    
    <h4>Send some coins</h4>
    <form action="">
      <label>Receiver</label>
      <input id="receiver" type="text" /><br>
      <label>Amount</label>
      <input id="amount" type="text" />
      <a href="#" id="sendCoins">Send coins</a>
    </form>
    <p id="notice"></p>
    <h4>data:</h4>
    <div id="data"></div>
    
  </body>
</html>


The only line to be manually updated is:

var contractAddr = "0x0da561f4332778bb5bf289c693f4000748b30080";

Where we set the correct address of the contract.

This loaded page looks like (once the demo is finished):




In order to swap between each account, we can enter some commands in the Javascript console:

Being that or:
eth.setCoinbase("0xcc9ba8b85a38d0f32c4f15c450e9c88170a2e839")

Initially only the cc9ba account has all the AlexosCoins. So that's the account from where we can transfer the AlexosCoins.

For some reason, if I try to make the transfer using the HTML page (by filling Receiver and Amount fields), the transaction never makes it to the Blockchain :(
No idea why.

My workaround was to instead perform the transaction directly from the AlethZero transact panel:



And to build the correct long string to fill the 'Data' window with (0x0000000000000000000000008b5aee50...), I obtain it from the javascript running in the HTML page:



Which was computed by doing:


var data = (destAddr + amount).unbin();


Et voilĂ , this wraps up the whole demo!