...by Daniel Szego
quote
"On a long enough timeline we will all become Satoshi Nakamoto.."
Daniel Szego

Saturday, January 6, 2018

Solidity and Truffle Tips and Tricks - testing events in unit tests


Supposing you want to check if an event has been raised during a unit test, you can simply use parts of the result variable. As an example result.logs[0].event shows the name of the raised event. 

 return Contract.functionCall(<parameters>);             
        }).then(function(result) {
            event = result.logs[0].event;
    assert.equal(event, "EventName", "Event raised"); 

Thursday, January 4, 2018

Solidity and Truffle Tips and Tricks - Invalid number of arguments in web3,js


If you work with solidity and truffle and you get the following error message form web3.js :

Invalid number of arguments to Solidity function

It can be resulted because something has gone corrupted in the build folder during the last build process. So simply delete the build folder and run:

truffle migrate --reset --compile-all

Solidity and Truffle Tips and Tricks - Ganache on Ubuntu


Ganache seems to a cool tool from Truffle for realizing a test rpc. However, it is still somehow at the beginning phase of the development. Sometimes it is not so trivial to set up, and sometimes not so sure how it will be integrated with the current test rpc from Truffle. 

Anyway if you want install on Ubuntu, use the following procedure:

git clone https://github.com/trufflesuite/ganache

run npm install

run npm start

Having deployed, make sure that the truffle.js file contains the correct host and port information, by default and configure truffle with same parameters as well.

host: 127.0.0.1
port: 7545 

If you want to use geth console on the top of ganache, you can simply run it from a different terminal:

geth attach http://localhost:7545



Tuesday, January 2, 2018

Solidity and Truffle Tips and Tricks - Overflows and safe arithmetic


One of the problem is with the solidity language that overflow or underflow of an integer value is not really checked at the moment. As a result, providing wrong values by chance or at a hacking attack can very easily cause unexpected behavior. As an example, considering the following function: 

    function add(uint8 _a, uint8 _b) returns (uint8) {
        return _a + _b;
    }

As add(100,10) result in 110 as expected add(255,10) results in 9 which is not surely intended as a result. If in such a situation, it is rather expected that an error is thrown indicating overflow, than for instance the following safe add function can be used:

    function addSafe(uint8 _a, uint8 _b) returns (uint8) {
        assert((_a + _b >= _a) && (_a + _b >= _b));
        return _a + _b;
    }  






Solidity and Truffle Tips and Tricks - Debug and log pattern


Solidity contracts are not really debuggable, even if you can use the minimum debugging functionality from Truffle, there is the place for a lot of improvement. The situation can be more critical if you have to debug your source code in the production environment, which is happen to be almost impossible. One way might be to have an explicit pattern that is capable to log information during execution. An example implementation can be seen bellow. The Loggable ancestor class provides the logging functionality that can be turned on or off by an administrator even in production.

Several problems exist though with this simple design that might be fine tuned in the future: 

1. The events can be only defined as public as a consequence nothing prevents in the descendant class calling directly the LogEvent instead of the Log function. It is possible something that can not better designed in the future, so it must be explicitly  paid attention that the Log function is called.

2. The logging event must be as cheap as possible from a gas consumption perspective. Current implementation cost about 600 gas if the logging turned off and 2500 if it is turned on. However with more logging logic this might be further improved.         

3. This logging is absolutely open for everyone to see, which is might not be a good idea on a public network in a production scenario. It is a general further question how secure logging with minimal gas overhead can be realized.  

contract Loggable
{
    bool public debug;
    address admin; 
    
    event LogEvent(string info);
    
    modifier isAdmin{
        require(msg.sender == admin);
        _;
    }
    
    function Loggable(){
        admin = msg.sender;
    }
    
    function setDebug(bool _debug) isAdmin public{
        debug = _debug;
    }
    
    function Log(string message) public{
        if (debug){
            LogEvent(message);
        }
    }    
}

contract Test is Loggable{
    
    function Test() public{
        Log("Test");
    }
}

Monday, January 1, 2018

Genetic and evolution algorithms and market


The blockchain application called cryptokitties provides some interesting ideas about genetic and evolution algorithms and the market. In classical evolution and genetic algorithms there is usually a target or fitness function to evaluate a certain population or individual and the goal is to minimize the difference between target value and the actual performance of the population. However the whole concept might be put into a market context. The mutated or combined entities of the population are exchanged or traded between different actors. As the time goes on, high value individuals are traded frequently or for a high price as less important individuals will have low liquidity and low price. Certainly, in this way the target value that is evaluated in each round depends on the subjective evaluation of the individuals taking part in the trade. As these subjective preferences might evolve over the time, it is pretty questionable in which direction does the algorithm converge.

Solidity gas optimization - creating child contract versus child struct


Solidity provides the way to create a new contract from an existing one with the help of the new keyword. It is important to note however that contract creation is one of the most expensive operation in solidity. If the use-case allows however you can simply use a struct instead if subcontracts. Certainly it must be payed attention how the functions are realized that should be associated with the child contract. In the bellow example creating the contracts with ContractFactory requires at least 4 times as much gas as creating almost the same functionality with StructFactory.    

contract SubContract{
    int subVariable;
    
    function SubContract(int _initValue){
        subVariable = _initValue;
    }
}

contract ContractFactory{
    SubContract [] subContract;
    
    function generate(){
        for (int i = 0; i < 10; i++) {
        SubContract newContract = new SubContract(i);  
        subContract.push(newContract);
        }
    }
}

contract StructFactory{
    
    struct SubStruct {
        int subVariable;
    }
    
    SubStruct [] subStruct;
    
    function generate(){
        for (int i = 0; i < 10; i++) {
        SubStruct memory newStruct = SubStruct(i);  
        subStruct.push(newStruct);
        }
    }
}

Solidity gas optimization - storage and local variables of basic types


If you have function that does some local computation, try to use access to the global poperties or variables of the contract as rarely as possible. Global variables of a contract represent always storage, so setting the variable relative often result in an enormous gas cost. On the contrary, local variables of basic types are stored in the stack so accessing them does not cost gas. In the following example testMemory has a couple of hundreds of gas cost, but testStorage a couple of hundred thousands. 

contract testContract
{
    int public storageInt = 0;
    
    function testMemory(){
        int j;
        for (int i = 0; i < 100; i ++){
            j++;
        }
    }

    function testStorage(){
        int j;
        for (int i = 0; i < 100; i ++){
            storageInt++;
        }
    }
}

Solidity gas optimization - memory arrays


Whenever, you have to make some internal computation in a solidity function with the help of an array, try to use memory arrays instead of storage. By default creating an array means storage location however if you know exactly the size of the array and you do not want to use "push" operator, you can use fixed size memory arrays.

function testStorage(){
    uint[100] i;
    i[1] = 1;
    i[2] = 2;
    i[3] = 3;
}

function testMemory(){
    uint[100] memory i;
    i[1] = 1;
    i[2] = 2;
    i[3] = 3;

As in "testStorage" each new value adding associated to the array cost about 20.000 gas, in the "testMemory" example accessing the values of the array practically does not cost anything.

Solidity and Truffle Tips and Tricks - iteration on a mapping


Mapping is a great structure in solidity, however a big drawback is to make an iteration on that. Basically it is not really possible, what you can do are the followings: 

1. If the key-space is small like working with uint8, you can iterate the whole key-space.
2.  You can use a pattern that adds the used key into an array as well, like bellow. Certainly this pattern increases the gas consumption.  

contract Iterrativemapping  {
  mapping(keyType = valueType) myMapping;
  keyType[] possibleKeys;

  function insert (keyType key, valuType value) public {
    possibleKeys.push(key);
    myMapping[key] = value;
  }
  
  function remove ....

  function setValue ...

}

3. Last but not least, you can create an event that is triggered at setting the value. Certainly this scenario does not provide a way to iterate on the mapping from a solidity contract, but there will be an off-chain log available about possible keys, values and about the whole history that can be evaluated off-chain.

contract Mappingwithevent {
  mapping(keyType = valueType) myMapping;

  event ValueSetEvent(keyType, valueType);

  function setValue (keyType key, valuType value) public {
    myMapping[key] = value;
    ValueSetEvent(key, value);
  }
  
}