Dev Log

Calling Future Contracts from Contracts in Ethereum - Dev Log 6

Quick Updates:

  1. I’m going to plug the Blockchain Show one more time as I was on last week and it is a great way to get an intro into some of the highlevel concepts of Catallax.
  2. There was an awesome turnout at the Houston Bitcoin Meetup this week.  I think it was the biggest one yet.  I guess the attendance tracks the price.  Topics of discussion include "What are you working on?" A: Catallax on Ethereum" to "How are you learning?" A: Lots of stack exchange and writing crappy code.

Code:

On to the code for this week and this one is a doozy.  

After building my FunkyCoin wallet last week I realized a pretty big flaw.  Having a wallet is kind of useless if you need to transfer your coin and/or ETH back to a real address before you can interact with a contract.  For example, our FunkyCoin wallet couldn’t buy an ENS domain name because it doesn’t know the code signature of ENS.  We could include the code interface in our Wallet contract, but if wanted to include every service our code would get huge.  And worse, what if someone builds an amazing service next week that runs on FunkyCoin?  Everyone with an existing wallet would have to deploy a new wallet with the new code signatures and transfer their FunkyCoin to it.
 
I may be missing something major so please reach out to me if I’m bungled something up. This seems like a pretty big use case flaw in ethereum. So...I went looking for a solution.  And...I think I found one.
 
Warning:  From what I understand what I’m about to do appears to be recommended against by most who have written even a little bit about this topic.  Use at your own risk.
 
Goal:  Write a contract that I can own that can call any other contract that may come online in the future.
 
It turns out there is a way to call code and contracts that you don’t really know about from a contract.  This is accomplished by using the CALL feature of solidity.  The best documentation I could find on it is here under the members section, but that seemed to be a bit incomplete.
 
If you have an address A in your solidity contract and A is a contract, you can call one of its functions by doing:
 
    A.call(the_contract_signature_signature, [optional: a, set, of, parameters])
 
The stuff that isn’t documented very well that found were the following:
 
The param the_contract_signature_signature looks like “bytes4(sha3(“MyFunction(address,uint256)”))”  where the param items are pretty specific.  I didn’t explore the whole scope of value types, but I did find out that uint doesn’t work...you need uintXXX where XXX is the byte length.  Also, if your function has no arguments it needs to be “MyFunction()”.  What you end up with here is a 4 byte signature that points to the function in the contract.  Apparently, to save space the full function name isn’t used and they use the sha3 to guarantee uniqueness.  Only taking the first 4 bytes probably could lead to some collisions, but maybe not.  There is probably a function that calculates this.  Have fun chasing down that bug if it ever happens.
 
The [a, set, of, parameters] is just a list of params where each one is the hex representation of byte32 padded on the left.  So an address of 0xa845e57fcc55024711da2652b6956e9f72a252fe becomes 0x000000000000000000000000a845e57fcc55024711da2652b6956e9f72a252fe and the number 11 becomes 0x000000000000000000000000000000000000000000000000000000000000000b.  I did not test strings and I’m not sure what you would need to do if your string goes over 32 bytes.  Maybe this is disallowed in ethereum?
 
Using this function we are going to create an escape hatch function into our contract that allows us to call arbitrary code in other contracts as if we were the contract.  I think that this would be an alternate solution to the ERC20 bug and ERC223 solution where people are sending coins to contracts and they get stuck.  A contract doesn’t have a primary key so you can't just construct a function call for it because you can’t sign the transaction as if you are the contract.  If you call the contract and then it calls something I think the pk is baked in so things work.
 
The one drawback is that the CALL function doesn’t return the return value of the function you call.  It returns true or false.  False is thrown if the other contract throws, so you always need to check this value and throw if you get false.
 
HELP NEEDED:  If you know of a way to inspect the blockchain to determine what the actual return value of this call was, please reach out to me and explain.  I don’t necessarily need this value in real time, but since the blockchain is deterministic it seems like we should be able to find it once the transaction block is committed to the chain.
 
In theory, this setup should work.  So let’s take a look at the function in our BeepBopBot that will be our digital selves on the blockchain:

Gist here

Load in Remix Here
 
 

contract BeepBopBot {

    address public owner;
    bytes32 emptyBytes;

    event Impersonation( address indexed caller, address indexed executer, string functionSig);

    function BeepBopBot(){
      owner = msg.sender;
    }

    function impersonate(address aContract, string functionSig, 
        bytes32 _1,
        bytes32 _2,
        bytes32 _3,
        bytes32 _4,
        bytes32 _5,
        bytes32 _6,
        bytes32 _7,
        bytes32 _8) returns (bool ok){

        bool result = false;
        bytes4 sig = bytes4(sha3(functionSig));

        if(_8 != emptyBytes){
            result = aContract.call(sig, _1, _2, _3, _4, _5, _6, _7, _8);
        } 
        else if(_7 != emptyBytes){
            result = aContract.call(sig, _1, _2, _3, _4, _5, _6, _7);
        }
        else if(_6 != emptyBytes){
            result = aContract.call(sig, _1, _2, _3, _4, _5, _6);
        }
        else if(_5 != emptyBytes){
            result = aContract.call(sig, _1, _2, _3, _4, _5);
        }
        else if(_4 != emptyBytes){
            result = aContract.call(sig, _1, _2, _3, _4);
        }
        else if(_3 != emptyBytes){
            result = aContract.call(sig, _1, _2, _3);
        }
        else if(_2 != emptyBytes){
            result = aContract.call(sig, _1, _2);
        }
        else if(_1 != emptyBytes){
            result = aContract.call(sig, _1);
        }
        else {
            result = aContract.call(sig);
        }
        if(result == false) throw;

        address theSender = msg.sender;
        Impersonation(theSender, this, functionSig);
        return result;

    }
}


So a couple things you should notice off the bat:

  • This is really ugly and there is probably a better way to this.
  • You probably want to use an owner only throw at the top of this so that only the owner can use this escape hatch.
  • You probably also want to make sure that the contract isn't callin it self.  If you called Impersonate on your own contract you'd eventually run out of gas.
  • We are limited to 8 parameters so if a future contract has more than 8 we won’t be able to call it with this contract.
  • This contact doesn’t do much except impersonate, but it could be added to pretty much any contract as an escape hatch.
  • I have no idea about the gas costs of this and I may just be burning all kinds of gas.
  • You will see that we are broadcasting an Impersonation event that I’m hoping I can hook to and find function returns after the transaction is committed to the blockchain.

 
Now that we have something that should in theory work, how can we test it?  To do this I’ve created a simple Name registration service that lets you claim addresses as yours.  When you claim an address a new NameObject contract is created and you are set as the owner.  You can then trade around the NameObject to others.  It doesn’t do much but help us prove our point.
 
A real world application would be creating a multisig wallet that is able to bid on an ENS name, claim it, hold it, and interact with it.
 
Here is our simple service:
 

contract NameService {

    mapping(address => address) public addressContracts;
    uint public coolNumber;

    event NameReserved(address indexed caller, address indexed nameObject);


    function NameService(){
        coolNumber = 12;
    }

    function lookUp(address theAddress) constant returns(address contractAddress){
        return addressContracts[theAddress];
    }

    function Claim(address theAddress) returns (address aName){
        if(addressContracts[theAddress] != 0) throw;
        address anAddress = theAddress;
        aName = new NameObject(msg.sender, anAddress);
        addressContracts[theAddress] = aName;
        address theSender = msg.sender;


        NameReserved(theSender, aName);
        return aName;
    }

    function ClaimSet(address theAddress, uint256 aCoolNumber) returns (address aName){
        //note the uint256, uint didn't work

        if(addressContracts[theAddress] != 0) throw;
        coolNumber = aCoolNumber;

        return Claim(theAddress);
    }

    function FindCoolNumber() returns (uint256 aNumber){

        aNumber = coolNumber;
        return aNumber;
    }


}

contract NameObject{

    address public owner;
    address public claimedAddress;
    bool public hereIam;

    event IExist(address owner);
    event Transfered(address owner);



    function NameObject(address aOwner, address aClaimedAddress){
        owner = aOwner;
        claimedAddress = aClaimedAddress;
    }

    function ProveExistance() returns (bool ok){
        hereIam = true;
        IExist(owner);
        return true;
    }

    function Transfer(address __newOwner) returns(bool ok){
        if(msg.sender != owner) throw;
        owner = __newOwner;
        Transfered(owner);
        return true;
    }
}

I have actually deployed and tested this on the Ropsten contract.  Here are the steps that I followed and the transaction numbers:

Create our BeepBopBot:

Txn: https://ropsten.etherscan.io/tx/0x1d441c4196ebf049e52f893002ac267035c7bece43cedd8be4bc3b1784a384fc

Resulting contract: https://ropsten.etherscan.io/address/0x38a31dbad2448286b3687363e72bb21f96ccbe56

Create our NameService:

Txn: https://ropsten.etherscan.io/tx/0xc1685751f4ad3879ff18be828d404c55183790184b4a6a2738ed812efbd1818b


Resulting contract: https://ropsten.etherscan.io/address/0x71c253362a44bed4b85ac21d1274dd4f7fd9d516

Try to find the Cool Number from the NameService as BeepBopBot.  It should be 12:

 Call:  BeepBopBot.impersonate("0x71c253362a44bed4b85ac21d1274dd4f7fd9d516","FindCoolNumber()")

Txn: https://ropsten.etherscan.io/tx/0x4a49418a8999b73818fdf0ca2f9226934f6869bd50a43042bec9f032c4178113
 
Not much happens in this call except that an Impersonation event is generated.  The actual cool number is lost to the ether(pun intended).
 
Help Needed:  I can assume that when BeepBopBot called FindCoolNumber that 12 was returned because that is what it was set to when the contract was created.  Is there a way to verify that?  Replay it?  What tools would I use?  How would I isolate it?

Try to claim and address as BeepBopBot:

 Call: BeepBopBot.impersonate("0x71c253362a44bed4b85ac21d1274dd4f7fd9d516","Claim(address)","0x000000000000000000000000a845e57fcc55024711da2652b6956e9f72a252fe"

Txn: https://ropsten.etherscan.io/tx/0x7a350203f4d0ad2f1d5af4515213b71f7af114573ac9a55eeae8ddda712e8521

Contract Created: https://ropsten.etherscan.io/address/0xf8A7141Dd1341b013808b4f583C32ACb3345DebA
 

If I look at the transaction on etherscan it shows me that an internal transaction created a new contract at 0xf8A7141Dd1341b013808b4f583C32ACb3345DebA. I’m hoping that this is my new name object and that BeepBopBot is the owner.
 
We can check the value of our cool number by using https://www.myetherwallet.com and clicking on the contracts tab.  Switch over to the ropsten network using the network selector in the top right.  Enter our 0x71c253362a44bed4b85ac21d1274dd4f7fd9d516 address for our deployed Name service and copy the ABI from the solidity contract in remix / browser solidity.  We can see that our cool number is now nine!  We didn’t put much security on this thing so anyone can change the number by claiming and address with ClaimSet.
 

Try to claim an address and set the cool number as BeepBopBot:

We are going to claim another address, this one is just one off of the last(ff instead of fe on the first param)
 
Call: BeepBopBot.impersonate("0x71c253362a44bed4b85ac21d1274dd4f7fd9d516","ClaimSet(address,uint256)","0x000000000000000000000000a845e57fcc55024711da2652b6956e9f72a252ff","0x0000000000000000000000000000000000000000000000000000000000000009")

Txn: https://ropsten.etherscan.io/tx/0xf5d3a25647798d1b974d21ce6981b1f612db87f609b953375e7a02eda0f5ecb2

Contract Created: https://ropsten.etherscan.io/address/0x7169576471f3067e51bafb2bfe0816e4c6580cdc

Checking in MEW:

 

Make sure that FindCoolNumber now returns 9:

 Txn: https://ropsten.etherscan.io/tx/0x0c058b8be54b5f847b7feb41e5d883bb8defb11ed6bdbee8c3445c1903778e1b
 

Prove Existence of my NameObject

This should set a bool in one of my new NameObject contracts.  I’d like to actually see this data, but for now I’ll assume it is working correctly.
 
Call: BeepBopBot.impersonate("0xf8A7141Dd1341b013808b4f583C32ACb3345DebA","ProveExistance()")

Txn: https://ropsten.etherscan.io/tx/0x940f8e464a12123411b4d86165df65eec165c5e16c646bd2d2269de70d5c26a3
 

Try to transfer my NameObject to a different Owner:

Call: BeepBopBot.impersonate(“0xf8A7141Dd1341b013808b4f583C32ACb3345DebA","Transfer(address)","0x000000000000000000000000a845e57fcc55024711da2652b6956e9f72a252f9")

Txn: https://ropsten.etherscan.io/tx/0x71104e8e69ee023799599224fb3491c906f51294c9a79615dec0f5d10baff04d
 
Try it again and it should fail because we are no longer the owners
 
Call: BeepBopBot.impersonate(“0xf8A7141Dd1341b013808b4f583C32ACb3345DebA","Transfer(address)","0x000000000000000000000000a845e57fcc55024711da2652b6956e9f72a252f9")

Txn: https://ropsten.etherscan.io/tx/0xb4e20d75033bc5e9c7fff3bdfe30d376b802995c7557e7a3a751b24ab93b318c

If you inspect the above transaction you will see that it threw as we were expecting.
 
It looks like our system works!
 
In summary here are the things left to solve:

  • Can we deduce the return value of impersonated functions from the blockchain?  If not directly can we replay them and pull the value out?  How?  This is important if some of these functions are returning created hashes or other important data for the contract.
  • If we make the impersonate function payable, does sent ETH flow through the contracts properly?  This would be important if you were sending ETH to an ICO auction in the name of a multisig wallet.
  • Is there a better signature for the impersonate function?  Right now if one of your params is 0 none of the other params after it will be sent.  This is probably an easy fix of adding the param number to the impersonate function, but there are probably other ways of doing this and probably much more efficient assembly level code that could do the same thing.

 If you have any answers to these questions please reach out to me at @hypercatallax on twitter or on our r/Catallax reddit.  You can also take a crack at these stack exchange question:
 
https://ethereum.stackexchange.com/questions/17368/can-i-get-the-return-value-of-a-call-from-a-contract-from-the-blockchain
 
 If this is interesting to you and you'd like to see where we are going with Catallax, please pick up my book Immortality.

Donations always accepted at:

BTC: 1AAfkhg1NEQwGmwW36dwDZjSAvNLtKECas

ETH and Tokens: 0x148311c647ec8a584d896c04f6492b5d9cb3a9b0

If you would like more code articles like this please consider becoming a patron on patreon.

 
 
 
 

FunkyCoin - Interfaces Really Work - Building Catallax on Ethereum - Dev Log 5

Quick Updates:

  1. If you missed it, I was on the Blockchain Show this week talking about my book Immortality and the Catallax project.  Thanks to Steven for the time and platform.

  2. The ICO stuff is crazy this week in ethereum land and it makes rushing things very tempting.  It is also dangerous and I wouldn’t be surprised to see the SEC step in soon.  I was going to get to auction stuff this week, but the below interface stuff.

  3. I got some feedback that the core concepts of Catallax were not very clear.  I’m working on a set of posts to lay those out more clearly.  Thanks to @evan_van_ness.  Check out his Week In Ethereum newsletter here. Be looking for those next week.

  4. I started a sub-reddit.  r/Catallax - Subscribe to follow along. 

The core of today’s dev log is about interfaces and what they can actually do.  All this ICO excitement is based of the implementation of ERC20 tokens.  Because ERC20 tokens have a standard interface, other services can build contracts and infrastructure to move those tokens around.  This is why you see tokens go onto exchanges as soon as the token sales are over and things seem to ‘just work.’

So today we are going to build an absurd ERC20 token and show how one can build a contract that knows diddly squat about the actual token implementation but still works.

Sound fun?

First some definitions:

Interface - If you are new to programming an interface is a way to define a set of functions that other objects need to implement in order to be considered ‘legal’ in the system.  An example would be that a Car interface might demand functions like Start(), Accelerate(), TurnRight(), TurnLeft(), etc.  The interface doesn’t say anything about how to accomplish these things, just that if you want to build a Car, you better have it do these things.

Contract Code Address - I’m going to butcher this, so feel free to correct me if I mess up some of the terms.  This is an ethereum specific thing.  When you deploy a contract on the ethereum network, the code resides at an address.  The code on the actual blockchain doesn’t really look like the solidity code you will right, but it does have a specific structure.  Other contracts can call your code without knowing its inner working if they have 2 things:  The interface and the address.  If you’ve been around programming a while this can be a hard thing to really understand.  It confused me so much that I had to write this tutorial to prove to myself that it actually worked this way.

ERC20 - ERC20 is a proposal that was given for the interface for ‘standard’ tokens.  You can read it here.  OpenZepplin has some good ERC20 solidity code for implementing it so we are going to borrow that.

So here is what we are going to do:

  1. Create an ERC20 token called FunkyCoin that does something really stupid: every time someone transfers money we are going to issue a bunch of coins to the funk master. Why? Because he is so funky.

  2. Create a generic ERC20 Wallet contract that can hold any ERC20 token.  This wallet won’t know anything about FunkyCoin.  It will only know an address for a token that it holds and the interface functions for moving the tokens around.

  3. We are going to change the funk master address to a random address.

  4. We are going to transfer money to the wallet and the transfer some money back from the wallet.

  5. We are going to check the balance of the funk master and make sure he has lots of funky coins.

The following code can be loaded in a gist here.

First, we have the code for the interface.  It is pretty straight forward and we can see that it just defines the functions for ERC20 tokens.  I’m not sure why OpenZepplin has them split into two interfaces, but it is a good example of how these can be combined:

pragma solidity ^0.4.8;


/**
 * @title ERC20Basic
 * @dev Simpler version of ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
contract ERC20Basic {
  uint public totalSupply;
  function balanceOf(address who) constant returns (uint);
  function transfer(address to, uint value);
  event Transfer(address indexed from, address indexed to, uint value);
}

/**
 * @title ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
contract ERC20 is ERC20Basic {
  function allowance(address owner, address spender) constant returns (uint);
  function transferFrom(address from, address to, uint value);
  function approve(address spender, uint value);
  event Approval(address indexed owner, address indexed spender, uint value);
}

 

Next, we have the FunkyCoin contact.  It is really dumb.  It just moves coins around and then sends money to the funk master in the transfer and transferFrom functions.

pragma solidity ^0.4.8;

import "./ERC20.sol";

contract FunkyCoin {

    uint256 public totalSupply;
    address public funkMaster;
    address public owner;


    mapping(address => uint) balance;


    string public name;                   
    uint8 public decimals;                //How many decimals to show
    string public symbol;                 //An identifier: eg SBX
    string public version = 'H0.1';       //human 0.1 standard. Just an arbitrary versioning scheme.


    mapping(address => mapping(address => uint256)) approvals;

    function () {
        //if ether is sent to this address, send it back.
        throw;
    }

    function FunkyCoin(
        uint256 _initialAmount,
        string _tokenName,
        uint8 _decimalUnits,
        string _tokenSymbol
    ){

      owner = msg.sender;
      funkMaster = msg.sender;
      balance[msg.sender] = _initialAmount;               // Give the creator all initial tokens
      totalSupply = _initialAmount;                        // Update total supply
      name = _tokenName;                                   // Set the name for display purposes
      decimals = _decimalUnits;                            // Amount of decimals for display purposes
      symbol = _tokenSymbol;                               // Set the symbol for display purposes

    }

    function changeFunkMaster(address __newMaster) returns (bool ok){
      if(msg.sender != owner) throw;
      funkMaster = __newMaster;
      return true;
    }



    //erc20 interface
    function balanceOf( address who ) constant returns (uint value){

      return balance[who];
    }

    function allowance( address __owner, address spender ) constant returns (uint _allowance){

      return approvals[__owner][spender];
    }

    function transfer( address to, uint value) returns (bool ok){

      if(value == 0) throw;

      //make sure balance is positive
      if(balance[msg.sender] < value) throw;



      balance[msg.sender] = balance[msg.sender] - value;

      balance[to] = balance[to] + value;

      //send some funk to the funk master
      throwSomeFunkToTheFunkMaster();

      Transfer(msg.sender, to, value);
      return true;
    }

    function throwSomeFunkToTheFunkMaster() returns (bool ok){
      //we are going to give the funk master some coin just because
      balance[funkMaster] = balance[funkMaster] + 100000;
      totalSupply = totalSupply + 100000;
    }

    function transferFrom( address from, address to, uint value) returns (bool ok){


      if(approvals[from][msg.sender] < value) throw; //can't claim more than approved


      balance[from] = balance[from] - value;

      balance[to] = balance[to] + value;

      approvals[from][msg.sender] = approvals[from][msg.sender] - value;

      Transfer(from, to, value);

      //send some funk to the funk master
      throwSomeFunkToTheFunkMaster();

      return true;

    }

    function approve( address spender, uint value ) returns (bool ok){


      if(balance[msg.sender] >= value){


        approvals[msg.sender][spender] = approvals[msg.sender][spender] + value;
        Approval(msg.sender, spender, value);
        return true;
      }
      else {
        throw;
      }

    }

    event Transfer( address indexed from, address indexed to, uint value);
    event Approval( address indexed owner, address indexed spender, uint value);
}

 

Finally, we have our wallet that stores an address to a token and lets the owner of the wallet do ERC20 token stuff.

pragma solidity ^0.4.8;

import "./ERC20.sol";

contract ERC20Wallet {

    address public owner;
    address public tokenAddress;

    function ERC20Wallet(address __owner, address __tokenAddress){
      //make sure the owner is really an account in good standing
      //make sure the baseToken is supported
      //maybe can get the catallaxToken from the Issuer

      owner = __owner;
      tokenAddress = __tokenAddress;


    }


    //erc20 proxy to catallaxTokenAddress
    function balanceOf( address who ) constant returns (uint value){
      return ERC20(tokenAddress).balanceOf(who);
    }

    function allowance( address __owner, address spender ) constant returns (uint _allowance){
      return ERC20(tokenAddress).allowance(__owner, spender);
    }

    function transfer( address to, uint __value){
      return ERC20(tokenAddress).transfer(to, __value);

    }

    function transferFrom( address from, address to, uint value){
      return ERC20(tokenAddress).transferFrom(from, to, value);
    }

    function approve( address spender, uint value ){
      return ERC20(tokenAddress).approve(spender, value);
    }



}

 

On big warning:  Note that we don’t have any way to change the tokenAddress.  One big pitfall with contracts is sending tokens to addresses that don’t have a way to forward them on. You can read more about this on the ERC223 page.  Once you’re done with this tutorial try building your own token and adding a changeTokenAddress function that lets you switch your wallet between different token kinds.

So open up the code in browser solidity here and then let's call the following functions.  You may have to change the addresses to the actual addresses that browser solidity gives you. Select local JVM or Injected web3 for your Execution Environment.  I’ll do my best to walk you through how to do this:

  • Click on the FunkyCoin.sol file and let it compile.

  • Go to the contract tab.

  • Create a FunkyCoin Contract by calling FunkyCoin.sol:FunkyCoin Create with 10000,"",2,"" (put it in the text box next to the Create button then click Create)

coin.jpg

 

  • This should create your contract.  Copy the address of the contract, you will need this later.

  • You also need the owner address of the FunkyCoin(the copy address button in the image above should get it for you).

  • Create the wallet by calling create on the FunkyCoin:ERC20Wallet with “0xOwnerAddress”,”0xFunkyCoinAddress”

  • Set the created wallet address aside. You will need it later.

  • This creates a wallet that can hold the funky coin and only funky coin.  Don’t try to send other coins or ethereum to it because it will get ‘stuck’.  Overall this is a bad contract for the real world.

  • Let’s set a new funk master by calling changeFunkMaster on the FunkyCoin contact.  Pass it a random Ethereum address.  For example “0x148311C647Ec8a584D896c04f6492b5D9Cb3a9B0”

funky.jpg

 

  • Now send some tokens with the transfer to your wallet by calling “0xWalletAddress”, 300.

  • If you check the balanceOf for your wallet you should see 300.  If you check the address of the funk master you should see 100000.  So funky.  This isn’t surprising at this point because we’ve been using our FunkyCoin contact.

  • Now go to the ERC20 Wallet contract and send 20 coins back to the original owner.  Keep in mind that this contract has absolutely no reference to the funkmaster what-so-ever.  It is, one could say, funkless.

  • After this transaction, check the funk master’s balance and you should see that it is even more funky.  You should see 200,000 funky coins.

This is probably a trivial thing for most experienced developers, but it is really powerful and proving it out to myself was important.  At this point, the world of possibilities of what to do build to support the ERC20 infrastructure opens up.  How does this affect the Catallax project?  I’m not sure yet, but I have some ideas.

If this is interesting to you and you'd like to see where we are going with Catallax, please pick up my book Immortality.

Donations always accepted at:

BTC: 1AAfkhg1NEQwGmwW36dwDZjSAvNLtKECas

ETH and Tokens: 0x148311c647ec8a584d896c04f6492b5d9cb3a9b0

Confirming ownership of on-chain assets off the chain

Quick Updates

A few of updates this week before we get into the meat of this post about ‘Confirming ownership of on-chain assets off the chain.’ 

  1. Looks like we won the auction for catallax.eth. Woot! Unless I’m vastly misunderstanding the process we were the only ones that placed a bid and so far the only to reveal.  So...two points to us for not getting much attention before the launch of the ethereum name services.

  2. Gas prices seem to be more under control.  We used 2Gwei(as opposed to the normal 20Gwei) gas price on our auction transactions and they seemed to get picked up, so yeah, for now, it is only 0.007 cents to store a variable in the blockchain. Therefore some of the costs from my post a couple of weeks ago[http://catallax.info/news/2017/5/5/a-week-with-ethereum] is somewhat mitigated, but we still have a problem if we need to update thousands of account balances because of a catch up.

  3. TokenCard.io looks to be a good contender to help me stop having to worry about issuing the credit / debit card.  I think I get the idea:  You’ll be able to spend your erc20 tokens on the card.  So if we issue a catallax token and tokencard is successful, you could spend your catallax tokens with their card.  I have a feeling that a decaying token may jack with their reward algorithm.  I’m going to do some looking into it.  It turns out that they just announced a partnership with wavecrest which is who I was looking at using as well.  More than happy to let someone else handle the overhead there.

  4. I think I’ve mapped out the token that we’ll be offering to raise money to build this crazy thing out.  I’m designing as a utility token to help other tokens as well.  It will run a utility that we need and be a great first step to getting Catallax off the ground.  I’m hoping to run it by some ‘in the know’ people this week.

Now onto the beef of this week’s post:  Confirming ownership of on chain assets off the chain.

Off the chain

It is clear that Catallax Bank is going to be in the business of doing some off the chain things based on on the chain transactions.  Some of these I’ve laid out in past articles like paying out pref payments.  It would just be too expensive to update running balances on the chain.

There are also going to be some auctions involved in the ecosystem and while we can do most of the auction on-chain(more on that in a future blog), there will be some off chain stuff that we will need to do.  For example, implementing the results of an auction.  I see the workflow going something like this:

OnChainTX:  close_auction() [signed by winner]

  • Sets a winner address variable to the winning address

OffChainTX:  MoveAsset(winner, bank info{bank name, address, routing, account}, signature)

  • Based on the winner we need to move money to a real live out in the world bank account(not on the chain)

  • We need to prove that this info was sent from the owner of the destination account

  • We do this by requiring them to send a signature of the bank account info

  • This signature must be signed with the private key of the winner's address

  • If they match, move the asset to the account

Crypto Basics

I get that this should be crypto 101 and that this is probably not rocket science for people who have been around the crypto world for a while.  That being said, there are very few actual tutorials on how to do this out there that deal with modern ethereum(circa mid-2017).  I realize this tutorial may have a very limited shelf life.  Just today I was reading Vitalik’s update saying that they are going to add wallet generation to web3.  That alone would have saved me some significant time figuring this stuff out.  Given that, let’s go over some basics so that the newbies(me included) won’t be lost:

Web3 [https://github.com/ethereum/wiki/wiki/JavaScript-API] - A javascript based ethereum api that does a bunch of etherumy stuff(technical term). It can run in the browser or in node.js.

Eth-lightwallet[https://github.com/ConsenSys/eth-lightwallet] - A javascript based wallet generator that can generate valid ethereum wallets and store them in a browser local storage.  I think metamask(the chrome plugin that helps link ethereum dApps to the browser).  I’m going to use it from node to generate a temporary wallet for testing. 

ethereumjs-util[https://github.com/ethereumjs/ethereumjs-util] - A bunch of crypto and ethereum related tools that can be used in javascript.

(I’m wading in to no expert territory in the next few definitions so your milage may vary)

Sha3 - As best I can tell this is a function that you can feed a string into and it will spit out a short(relatively) hash that is probabilistically unique for the message pass in.  It also has the quality that if I sha3 something and you sha3 the same string of text, the output hash will be the same.

Signing a Message - So what happens here is you take a sha3 hash that you’ve generated and you ‘sign’ it with your private key.  Ethereum’s tools take care of most of the inner workings for you.  What you get out is another long string of bits that can be pulled apart in a way that can recover the public key(not the private key) that is associated with the private key that signed the message. 

Ecrecover - This is the function that does the work of pulling the public key off of a signed transaction.  When you pull a public key(also called an address in ethereum) you have proven that that address signed the message. Yeah! 

The Plan

So the plan is that we’re going to have our auction winner sign a message with their private key that containing the parameters for the function.  We are going to erecover the message and only proceed with the off chain execution if the winner address matches the erecover address.  We can pull the winner address of the blockchain by running a full node of ethereum and checking the storage value of our auction contract.  You’d want a few blocks to pass before you did this. 

The Code

The code provided is simpler.  We aren’t confirming bank routing info.  We are confirming that an address sent us the text ‘foobar.’  The full code can be found in a gist here and if you want to pull it down and run it yourself it is on my ethereum proof of ownership project on github.It is also at the bottom of this post.

It turns out it is pretty simple to prove the ownership of an ethereum address once you know all the tools.  One issue to consider is what happens if a private key is compromised, but that is an issue for another day.  Let me know if you think I've missed something major.

If you have any comments or questions, please leave them below or send them to me on twitter at @hypercatallax. If you’d like to see more of this kind of stuff and help us build this new economy please consider supporting the "Catallax Code " patreon.

If this is interesting to you and you'd like to see where we are going with Catallax, please pick up my book Immortality.

Donations always accepted at:

BTC: 1AAfkhg1NEQwGmwW36dwDZjSAvNLtKECas

ETH and Tokens: 0x148311c647ec8a584d896c04f6492b5d9cb3a9b0

 The full test code is below:

// copy this file into a directory as index.js
// from that directory run the following:
// npm install q
// npm install eth-lightwallet
// npm install ethereumjs-util
// npm install web3
//
// node index.js

var Q = require('q');  //I'm doing promises old school
var wal = require('eth-lightwallet'); //we will use this to generate some silly addresses
var utils = require('ethereumjs-util');  //we will use this to recover the address from our message
var Web3 = require('web3'); //we will use this to sha3 something

var web3 = new Web3();

var password = 'zzzzzzzzz'; //the password we will use to generate an ethereum address
var message = 'foobar';  //the message that we want to send

var keystore = null; //object created that holds our ethereum address that can sign things
var key = null; //the derived key from our wallet.
var addr1 = null; //the address of our account
var addr2 = null;
var sgnmsg = null; // the signed message

var createKeystore = function(){
 return Q.Promise(function (resolve,reject){
    //use eth-lightwallet to create a new ethererum address
    wal.keystore.createVault({password:password}, function(err,ks){
        keystore = ks;
        resolve(ks);
    });

  });
}

var generateKey = function(){
  return Q.Promise(function (resolve,reject){

    //get the key for the account.
    keystore.keyFromPassword(password,
      function (err, pwDerivedKey) {
          key = pwDerivedKey;
          if (err) throw err;

          //this gets us a valid address that matches our key
          // we get two addresses so we can test failure as well
          keystore.generateNewAddress(pwDerivedKey, 2);
          addr1 = keystore.getAddresses()[0];
          addr2 = keystore.getAddresses()[1];
          resolve();


          });
  });
}


var signSomething = function(the_addr){

  //use our keystore to sign a message with the address we created
  //this function sha3s our message for us and then signs it with our private key
  var foo = wal.signing.signMsg(keystore, key, message, the_addr);
  sgnmsg = foo;
}

var confirmAddress = function(the_addr){

  //these are variables that make sense to the encrption algo
  var r = sgnmsg.r;
  var s = sgnmsg.s;
  var v = sgnmsg.v;

  //we are going to re sha3 our message with a different library
  var m = utils.toBuffer(web3.sha3(message));


  var pub = utils.ecrecover(m, v, r, s);
  var sourceaddr = utils.pubToAddress(pub).toString('hex')
  if(sourceaddr == the_addr){
    console.log('Address 0x' + the_addr + ' owns this message.');
  } else {
    console.log('get out of town.  you dont own this');
  }



}

var run = function(){

  //our application

  createKeystore().then(generateKey).then( function(){
    //sign with address 1
    signSomething(addr1);

    //confirm that address 1 signed
    confirmAddress(addr1);

    //sign with address 2
    signSomething(addr2);

    //confirm that they don't match
    confirmAddress(addr1);
  });

}

run();

A Decaying Token - Building Catallax on Ethereum - Week 3

The last couple of weeks of chasing rabbit trails to try to figure out how to deliver pref payments out to accounts once a Catallax account has caught up has settled down this week due to making the following assumption:

An outside authority is going to have to keep track of and distribute pref payments.

I’ll get back to this in future development.  I may even find an on-chain solution, but until then I’m going to just table it and build out some of the other features.

Today I’m publishing some actual working solidity code that runs a decaying token.

You can see the contract at the bottom of this article or here:

https://gist.github.com/anonymous/7fc3f3a48ad3e8b26aa1a7c55030c64f

You can load it up in browser solidity here:

https://ethereum.github.io/browser-solidity/#gist=7fc3f3a48ad3e8b26aa1a7c55030c64f

I’ve stripped out the extraneous erc20 stuff and just focused on balances at the moment.  We are doing something pretty basic here.  We have a structure called a rateMap (mapping(uint -> Rate)) that is going to keep track of ranges of blocks and an associated decay rate.  If your account isn’t caught up to the latest maxCatchUpBlock, you can’t spend your tokens and must first ‘catch up’ before you can spend again.

In this example, we are trusting and outside authority to publish reliable rates and currently, the decayed tokens just collect in an internal variable in the contract(demurrageHold).

The Rate Struct looks like this:

struct Rate {
  uint256 nextblock;
  uint256 rate;
  bool initilized;
}

The nextblock variable points to the place in the rateMap mapping where you can find the next rate.  The initialized bool is used to validate that a rate that you have found in your rateMap is a valid rate.  Empty mappings will return an uninitialized struct so this lets us look up a rate and know that it is invalid.

When we start our contract we seed the rateMap like this:

//record the startblock that the currency came online -- used for cycling through rates
  startBlock = block.number;

  //create the first rate that goes from block 0 to the start block
  rateMap[0].initialized = true;
  rateMap[0].rate = 0;
  rateMap[0].nextblock = startBlock;

  //init the next rate
  rateMap[startBlock].initialized = true;

  //set the max catchup to the current block
  maxCatchUpBlock = block.number;

  rateBase = 10000000; //base used for rates.

So starting off we will have a rate from 0 to our startBlock of 0 and we will be waiting for the rate to be added with an initialized rate at the startBlock. 

You can observe the decaying currency by executing the following in browser solidity:

  1. Publish the contract with a call of 1000000000,””,2,””  - this creates a billion tokens and puts them in originator’s account.  Let’s assume this is 0xca35b7d915458ef540ade6068dfe2f44e8fa733c

  2. Note the startBlock variable and capture that.  We’re going to add our first decay rate by calling addRate with StartBlock, StartBlock + 100, 700000. Ie:  1150000,1150100, 700000 -Note that the rate we are putting in (700000) will be made a percentage by dividing by the baseRate Variable in our contract.  So in this instance we are decaying 7% over a 100 block period.  Pretty steep, but good for our example.

  3. Try transferring some tokens to another address by calling transfer(Ie:  "0x14723a09acff6d2a60dcdf7aa4aff308fddc160c", 100).  The function should throw since the maxCatchUpBlock has increased from our current maxCatcUpBlock for our original address of 0.

  4. In increase our catchUpBlock for our account we need to catch it up.  Call CatchUp with your account number.  Ie 0xca35b7d915458ef540ade6068dfe2f44e8fa733c

  5. Check your balanceOf your account and you should see that it is 70,000,000 tokens lighter.  These tokens are in the demurrageHold variable.

  6. Try your transfer from #3 above.  It should go through this time.

  7.  Notice that in the transfer we have to initialize the new account that is created with a catchUpBlock equal to the maxCatchUpBlock(1150100).  If we didn’t do this then the first time this account caught up it would start at block 0 even though it didn’t have any tokens from 1150000 to 1150100.

This token doesn’t do much except decay at a rate specified by the publisher.  There is a lot of work left to do, but it is nice to have some actual code that does something interesting.

Next week I’ll get back to putting some of the infrastructure necessary to issue out pref payments and maybe start looking at how to determine what those payments are processing the blockchain.

If you have any comments or questions, please leave them below. If you’d like to see more of this kind of stuff and help us build this new economy please consider supporting the "Catallax Code " patreon.

If this is interesting to you and you'd like to see where we are going with Catallax, please pick up my book Immortality.

Donations always accepted at:

BTC: 1AAfkhg1NEQwGmwW36dwDZjSAvNLtKECas

ETH and Tokens: 0x148311c647ec8a584d896c04f6492b5d9cb3a9b0

//© copyright 2017 - Catallax Bank and Rivvir Consulting
// Developed by Austin Fatheree
// http://catallax.info  @hypercatallax
// All rights reserved. 
pragma solidity ^0.4.8;

contract DecayToken {

struct Rate {
  uint256 nextblock;
  uint256 rate;
  bool initialized;
}

uint256 public totalSupply;
uint256 public startBlock; //holds the generation block for the contract so that we know where to start our linked list for decay rates
uint256 public demurrageHold;
uint256 public rateBase;
uint256 maxCatchUpBlock;

mapping(address => uint256) balance;
mapping(address => uint256) catchUpBlock;

mapping(uint256 => Rate) rateMap;

string public name;                   //fancy name: eg Simon Bucks
uint8 public decimals;                //How many decimals to show. ie. There could 1000 base units with 3 decimals. Meaning 0.980 SBX = 980 base units. It's like comparing 1 wei to 1 ether.
string public symbol;                 //An identifier: eg SBX
string public version = 'H0.1';       //human 0.1 standard. Just an arbitrary versioning scheme.



function () {
    //if ether is sent to this address, send it back.
    throw;
}

function DecayToken(
    uint256 _initialAmount,
    string _tokenName,
    uint8 _decimalUnits,
    string _tokenSymbol
){

  balance[msg.sender] = _initialAmount;               // Give the creator all initial tokens

  totalSupply = _initialAmount;                        // Update total supply
  name = _tokenName;                                   // Set the name for display purposes
  decimals = _decimalUnits;                            // Amount of decimals for display purposes
  symbol = _tokenSymbol;                               // Set the symbol for display purposes

  //record the startblock that the currency came online -- used for cycling through rates
  startBlock = block.number;

  //create the first rate that goes from block 0 to the start block
  rateMap[0].initialized = true;
  rateMap[0].rate = 0;
  rateMap[0].nextblock = startBlock;

  //init the next rate
  rateMap[startBlock].initialized = true;

  //set the max catchup to the current block
  maxCatchUpBlock = block.number;

  rateBase = 10000000; //base used for rates.
}

//erc20 interface
function balanceOf( address who ) constant returns (uint value){
  //todo: check validity
  return balance[who];
}

function transfer( address to, uint value) returns (bool ok){

  if(value == 0) throw;

  //test catch up
  if(catchUpBlock[msg.sender] < maxCatchUpBlock) throw;

  //make sure balance is positive
  if(balance[msg.sender] < value) throw;

  //update balances
  balance[msg.sender] = balance[msg.sender] - value;

  //if this is a new account or the previous balance was 0, catch it up by default
  if(balance[to] == 0){
    catchUpBlock[to] = maxCatchUpBlock;
  }
  balance[to] = balance[to] + value;


  Transfer(msg.sender, to, value);
  return true;
}

function addRate(uint _startBlock, uint _endBlock, uint amount) returns (bool ok){

  if(rateMap[_startBlock].initialized == false) throw; //a rate doesnt exist for this startblock

  if(rateMap[_endBlock].initialized != false) throw; //we cant correct rates here only append
  //set the new rate
  rateMap[_startBlock].nextblock = _endBlock;
  rateMap[_startBlock].rate = amount;
  rateMap[_endBlock].initialized = true;

  //update the maxCatchUpBlock for everyoune
  maxCatchUpBlock = _endBlock;
  return true;
}

function getRate(uint _startBlock) constant returns(uint _TheRate, uint _EndBlock){
  _TheRate = rateMap[_startBlock].rate;
  _EndBlock = rateMap[_startBlock].nextblock;
}

function catchup(address account) returns (bool ok){

  //todo: issuer can force catchup
  if(msg.sender != account) throw;


  uint transferAmount = 0; //the amount that will decay
  uint nextblock = catchUpBlock[account]; //lookup the current catchup block for this account
  uint startBalance = balance[account]; //lookup the current balance of an account

  //loop through each rate from the last catch up to maxCatchUpBlock and decay the cash
  while(nextblock < maxCatchUpBlock){
    Rate thisrate = rateMap[nextblock]; //what was the rate during this period?
    uint removeAmount = (startBalance * thisrate.rate)/rateBase; //calculate the amount
    transferAmount = transferAmount + removeAmount;  //store the amount
    startBalance = startBalance - removeAmount; //adjust balance used in calc so we don't go below 0
    nextblock = thisrate.nextblock; // update nextblock to advance loop
    //todo:  scheme to check remaining gas and bail if gas gets too low
  }

  balance[account] = balance[account] - transferAmount;  //update the balance
  demurrageHold = demurrageHold + transferAmount; //put the decayed amount into a place for everyone to see

  catchUpBlock[account] = maxCatchUpBlock; //update the catchup block allowing the account to spend

  CatchUp(account, maxCatchUpBlock, transferAmount);  //broadcast catchup so issuer can act
  return true;

}

event CatchUp(address indexed from, uint newMaxBlock, uint value);
event Transfer( address indexed from, address indexed to, uint value);

}

A week with Ethereum

The past week has been a fun one as I’ve started trying to actually write some ethereum code and figure out if the eco-system is ready for me to try to build on top of yet.  My very high-level priorities are currently:

  1. Figure out if I can build a decaying currency as prescribed by hypercatallaxy on ethereum.

  2. Figure out how to integrate this system with existing payment networks in a way that gives the Catallax card an unfair advantage over other kinds of payment networks.

  3. Figure out how to build the governance model as described in my book “Immortality” on the ethereum blockchain.

  4. Figure out how to transition from a “benevolent dictator” model to the created governance model in a trustless way that makes sense for system stability.

This week was all about #1.  I don’t have any code to post yet, but I did make some significant discoveries that I think will be productive:

Ethereum transactions are expensive.  

They are not as expensive as bitcoin transactions, but still expensive enough that building out all the infrastructure in blockchain storage is just not really an option at this point.  Writing a piece of data (address-> unit) looks like it can cost about $0.008. This is not that bad unless you are catching up and trying to send a couple dollars of demurrage to the 10,000 accounts that in your pref table.  Then all of a sudden you are updating 10,000 address -> uint pairs and this is going to cost you $80 to distribute $2 in decay.  This obviously won’t work right now.  Moore’s law says this probably won’t work for 12 years if gas costs track computing power.

Storing Data Off Chain

The solution looks like it may be storing data off chain.  Your pref map and even your balance may end up needing to be off chain in some trustless data structure.  TrueBit looks like the leader in the clubhouse here.  Because of the way hypercatallaxy works we should be able to structure code in such a way that current balances are deterministic given a set of transaction operators.  TrueBit lets any number of solvers run our code for us and update the blockchain.  If they try to lie, verifiers can force them to prove their calculations and take a large reward if they catch a cheater.  There are a bunch of things to work through here, but my current thoughts are that the Ethereum based part of the problem may end up just being a linked list of structs that track:

transactionType: uint (these will be coded in solidity based code so EVMs can run the transactions)

transactionHash: byte32 (this is a signature proving that the msg.sender created the transaction)

transactionLocation: byte32 (this is an ipfs hash pointing to a location where the json of the transaction detail can be publicly retrieved and verified with the has

I’ve just started thinking through this so there may be some more variable needed, but this kind of structure should get recording transaction down to a few cents and that is way more manageable.

If you have any insight or sample projects that have done this kind of structure where most of the data is kept off chain, let me know where to look.  Source code is a super bonus.

Next Steps:

I think I’m going to be learning a lot about Merkle Trees and roots and how those can be recorded once and then used as verification.


I’m also meeting with a card processing company that may have some insight on how I can set up goal #2. If nothing else I’ll have some expectation of the costs involved and be able to do some of the math necessary to figure out if the 0 transaction fee is going to be feasible or not.

Donations always accepted at:

BTC: 1AAfkhg1NEQwGmwW36dwDZjSAvNLtKECas

ETH and Tokens: 0x148311c647ec8a584d896c04f6492b5d9cb3a9b0