...by Daniel Szego
quote
"On a long enough timeline we will all become Satoshi Nakamoto.."
Daniel Szego
Showing posts with label Truffle. Show all posts
Showing posts with label Truffle. Show all posts

Saturday, November 24, 2018

Truffle and solidity tips and tricks - test events in unit tests


If you use truffle and want to test solidity with javascript unit test, you might want to test the raised events as well. As result gives back the whole transaction including the event log, the easiest way to get the event is to get them directly from the event log:

   return ContractInstance.functionCall({from: accounts[0]});       
   }).then(function(result) {

- result contains the whole transactions
result.logs contains the whole log
- result.logs[0].event contains the first event

So, an assert that checks if an event was raised might simply look like:

assert.equal(result.logs[0].event, "EventName", "Event raised");



Friday, November 23, 2018

Truffle and solidity tips and tricks - error at contract deployment gas amount


If you deploy a contract with the help of truffle possibly on a development environment and you get the following error message: 

"Error encountered, bailing. Network state unknown. Review successful transactions manually 
Error: The contract code couldn't be stored, please check your gas amount."

Well, there might be the problem of the real gas amount at the deployment, but most typically you want to deploy a contract that has an abstract method, or it inherits coincidentally and abstract method that is not implemented. 

Sunday, May 6, 2018

Solidity and Truffle Tips and Tricks - delete build folder


If you use solidity with truffle, sometimes it is a good idea to delete the entire build subdirectory, it will recreated anyway as you make a new compile. As an example if you get the following error message: "Attempting to run transaction which calls a contract function, but recipient address  ... is not a contract address" the resolution is simply delete and recreate the build folder. It happens regularly if you copy paste your solidity code for example between your local truffle environment and for instance remix.  

Sunday, February 4, 2018

Solidity and Truffle Tips and Tricks - order of modifiers


If you have several modifiers in a solidity function these modifiers might be dependent from each other, hence they might self modify the world state giving the possibility for another precondition for the next check. Anyway, the order of evaluation is from left to right as probably expected. So executing the test() function in the following code results "three"in the num variable. 

contract TestContract {
    string public num = "zero";
    
    modifier one(){
        num = "one";
        _;        
    }
    
    modifier two(){
        num = "two";
        _;        
    }

    modifier three(){
        num = "three";
        _;        
    }

    function test() one two three {
    }
}


Wednesday, January 10, 2018

Solidity and Truffle Tips and Tricks - setting up development environment with Parity



1. Install Parity: you can install parity on Ununtu or Linux with the following one line command:

 bash <(curl https://get.parity.io -kL)

2. Start development blockchain with Parity: for starting Parity development environment simply type start parity with the following parameters:

 --config dev or --chain dev for the development envrionment
 --force-ui for having a user interface
 --base-path set a base path as well, otherwise not really working for some reason.

by default, the local web environment as http://localhost:8180, you can create some new accounts, transfer ether from the development account to the others. It is an important information that the passphrase for the development account is simply an empty string. 

3. Configure Truffle with Parity: configure with the locally installed Parity environment in truffle.js as: 

networks: {
    parity: {
      host: "127.0.0.1",
      port: 8545,
      from: "0x00a329c0648769A73afAc7F9381E08FB43dBEA72",
      network_id: "*", // Match any network id
      gas: 4600000
    }
  }

It is a good idea to put some gas limit into the config file, as the parity gas limit configuration might not match with the default of Truffle.

4. Deploy with Truffle: migrate to the local parity network and test in the user interface under txqueue viewer if the transaction has been mined. Pay attention that truffle migration deploys more than one contract, so you have to sign the transaction on the graphical user interface more than once. 

 truffle migrate --network parity --verbose-vp

5. Test your contract with Parity


Sunday, January 7, 2018

Solidity and Truffle Tips and Tricks - unit tests and states


Truffle initializes new the state of the smart contracts (or deploys them new) both at the beginning of the testing and at each contract keywords. This practically means each new test starts from the state that is initialized by the migration script. From a practical point of view the following statement means a complete new initialisation or deployment:

contract('Contract', function(accounts) {
...

Solidity and Truffle Tips and Tricks - unit test from a different account


Supposing you want to carry out a unit test from a specific account that is different as the default account, you can basically use the accounts array that is initialized by the truffle development environment and you can explicitly set a specific account as accounts[i] at the function call:

contract('Contract', function(accounts) {
 it("test Contract other account", function() {
  return Contract.deployed().then(function(instance) {
   return Contract.callFunction( <parameters> {from:accounts[i]});  
   }).then( 
...
...

Solidity and Truffle Tips and Tricks - testing errors as unit tests


Supposing that you have to write a solidity unit test and you expect the result as an error message, you can use the following pattern, simply using catch in the unit testing instead of or beside then

contract('Contract', function(accounts) {
 it("test Contract from wrong account", function() {
  return Contract.deployed().then(function(instance) {
   return Contract.callFunction(<params>); 
  }).then(function(balance) {
   assert(false, "Call should not be allowed");            
  }).catch(function(error) {
   errorMessage = error.toString();
   if (errorMessage.indexOf("invalid opcode")  > 0){
    assert(true, "Call should not be allowed - error as expected");     }
    else{
   assert(true, "Call should not be allowed - wrong message");   
    }
   });
  });
});

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

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);
  }
  
}

Friday, December 29, 2017

Solidity and Truffle Tips and Tricks - setting up Truffle development environment


As I install a brand new environment usually with a brand VMware image, it is time to summarize the necessary steps instead of google-ing them always again and again.

1. Install brand new Ubuntu, I usually use the 16.04 version.

2. Installing open vmware tools:

 sudo apt-get install open-vm-tools
 sudo apt-get install open-vm-tools-desktop

3. Install packages:

 sudo apt-get update && sudo apt-get -y upgrade
 sudo apt-get -y install curl git vim build-essential

4. Install NodeJS:

 curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
 sudo apt-get install -y nodejs
 sudo npm install -g express

5. Install Truffle

 sudo npm install -g truffle

6. Install TestRPC

 sudo npm install -g ethereumjs-testrpc

7. Test: you can test the whole installation for instance by initializing a new project by Truffle:

 mkdir test
 cd test
 truffle init
 truffle develop

8.  Install Visual Studio Code, you can install fully from command prompt with the help of the following commands:

 curl https://packages.microsoft.com/keys/microsoft.asc | gpg -- dearmor > microsoft.gpg
 sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg
 sudo sh -c 'echo "deb [arch=amd64]  https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list'
 sudo apt-get update
 sudo apt-get install code

9. Last but not least, install the solidity extension under Visual Studio Code extentions

 









Thursday, December 28, 2017

Solidity and Truffle Tips and Tricks - gas limit, gas exceptions


If you reach different gas limits during the development and testing your contract and you get different exceptions like out of gas exception or gas limit exceeded, you can do the following things.
- configure the given gas explicitly at the contract creation or at the function execution, like:  

testContract.functionCall(_functionParameter, {gas:4700000});

- or configure the block gas limit in the truffle environment to your testRPC by modifying the truffle.js configuration file and adding explicit block gas limit, like:

  networks: {
    develop: {
      host: "localhost",
      port: 9545,
      network_id: "*",
      gas: 4700000
    }
  }

Note however that the block gas limit on the live network is around 4700000 at the moment, so truffle at this current release do not let you go above this parameter.


Monday, December 25, 2017

Solidity and Truffle Tips and Tricks - updatable smart contract


Ethereum Smart Contracts are immutable by design, meaning that if you deployed them, there is no way to update. However, with some tricks there is the possibility to make updates at least to a certain level.  

- client side: one way might be to handle everything on the client side, like deploying a new contract and simply forgetting the old one in a way that all client references are set to the new one. Certainly, it is not a very reliable or professional way of doing things.

- selfdestruct: one way of doing it is to implement selfdestruct into the contract, destroy the contract and develop a new one. Certainly, it a highly centralized way of doing things, hence you should probably provide a provable way to migrate the data of the old contract to the new one.   

- data dependent execution: another way might be if you explicitly implement several execution logic into the smart contract and the execution is dependent on an internal variable. Certainly, the disadvantage in this scenario that you have to prepare to every possible execution path:

contract DataDependenExec{

  uint _execPath = 0;

  function execute() public {
    if (_execPath == 0) {
       // ... execution path one
    } else {
       // ... execution path two
    }
  }

  // .. some functionality to set _execPath 
}

- multiply smart contracts: a further solution might be that the contracts are organized in a master - slave style and cooperation via a certain interface is realized. If the slave contract is updated, the master calls the new functionality. Certainly, the interface have to be designed very carefully, in a way that no change happen in the fingertip of the function and of course security has to be taken pretty seriously as well. 

contract Master{

  address _slaveAddress;

  function changeSlave (_newAddress) public {
    _slaveAddress = _newAddress;
  }

  function callSlave () public {
     Slave slave = Slave (_slaveAddress);
     slave.callSlaveFunction();
  }
}

contract Slave{

  function callSlaveFunction(){
    ...
  }
}

Solidity and Truffle Tips and Tricks - estimate gas usage


Estimating the gas usage is a critical part of every Ethereum Smart Contract. If you use Truffle and test rpc, the easiest way is to write a unit test for each critical function as a transaction. If a function is separated into several subcalls, it is a good idea to cover each of the sub-function separately from an individual unit test as an individual transaction. Having the individual tests, you can start a new console windows with truffle develop --log, in which you can see the gas consumption of each transaction. As gas consumption might be dependent from data, it can be a good idea to measure each transaction with several possible data input. 

Friday, December 22, 2017

Solidity and Truffle Tips and Tricks - important Truffle console commands



eb3.eth.accounts[0] - getting the address of an account address

SmartContract.address - getting the smart contract address

SmartContract.deployed().then(inst=>{SmartContractReference=inst}) - getting a real SmartContract reference if it is deployed

SmartContractReference = SmartContract.at(tokenAddress) - getting a real reference if the tokenAddress is previously known

SmartContractReference.callFunction().then(res => res.toNumber())
- calling smart contract function with converting the result value

SmartContractReference.sendTransaction({ from: account1, value: web3.toWei(5, "ether")})
- sending ether to smart contract








Wednesday, December 20, 2017

Solidity and Truffle Tips and Tricks - public, internal and private


General visibilities in solidity both for variables and functions mean the following:

- public: it can be called from overall, from outside the smart contract, from inside or from a descendant class. With variables it is a little bit special, at properties public means that a special getter function is generated that makes possible to read out the value of the property from outside. It must be paid attention however, because this is an automatically generated function that must be called in some scenarios, like from another contract or web3.js as function and not as a property.   

- internal: internal can be used / called only from the same contract or if there is an inheritance from descendant contracts. 

- private: can be called only from the contract itself. Not even a descendant contract is able to access the property or the function.

In functions there is one more option to take into considerations, using public or external. See the previous blog about the consideration of distinguishing the two modifiers.