Utilizing Event Logs in Solidity for Contract Design

contract-designremixsolidity

I noticed the following behaviour of event Log and wanted to confirm if that was the way it is supposed to work.

Code below. Function create requires two fields. I put "require" in place to check if the fields are non-zero and not empty.

If I only input a single field – say "name", it errors out as expected. I entered a empty field for name and 10 for number as: "",10. Solidity reads it correctly and identifies which element has the problem.

However – when function "create" errors out, it does not show any of the preceding Log statements within the function. I was expecting the Logs to be printed sequentially and stop when the failure is detected.

I had the following questions:

  1. When the function fails – does it ignore all the event Logs within the function? If so, is there another way to run this to show the Logs sequentially for debugging purposes.
  2. When "require" fails: does it automatically return default (which in this case is false). This is probably good because we do not have write return statements after every "require" checks.

    pragma solidity ^0.4.15;
    contract ABC {
        bytes32 public name;
        uint public number;

        event Log(string _myString);

        function ABC (bytes32 _name, uint _number) public {
            Log("Creating Object");
            name = _name;
            number = _number;

        }
    }    
    contract XYZ {

        ABC myABC;

        event Log(string _myString);

        function create(bytes32 _name, uint _number) public returns (bool isSuccess) {

            Log("checking name");
            require(_name != "");

            Log("name valid, now checking number");
            require(_number != 0);

            Log("name and number non-empty, creating a new contract");
            myABC = new ABC(_name,_number);

            Log("new contract created");

            return true;

        }
    }

Best Answer

In Solidity, there is no partial function execution. If at any point in the function there is an error thrown, the entire function fails and none of your logs would be logged. Actually all the logs would appear in the same transaction object created upon completion of the entire function, they would not be output one by one.

You can think of require as similar to an if (condition) revert(), where no state changes are made; when there’s a throw, everything is reverted to the initial state (ie nothing happens) except for the gas used to make the function call.

If you want to debug step by step, you can use remixd (https://remix.ethereum.org/) which has a step by step debugging tool.

There is also work being done on later versions of Solidity to make error messages more descriptive, so instead of just “invalid opcode”, later versions may allow for you to describe your throw message.

Related Topic