24

In Solidity (0.3.2) I am aware that there is no way to throw specific exceptions. (Everything is an invalid JUMP error.) It seems beneficial to have a way to log specific errors. Does it make sense to create an Error event to be fired before any exception? Are there any downsides I am not thinking of?

event Error(string message);

...

if(msg.sender != owner) {
  Error("User not authorized");
  throw;
}

EDIT: It appears that the event does not get logged at all if the transaction fails. Can someone confirm?

29

With an exception, as with throw, all effects (including events) of a transaction are reverted, except for the payment to the miner. So there would be no benefit in firing an event before a throw.


Possible Alternative

If full reversion via an exception isn't required, an error code might be usable.

Example:

contract C {
  function foo() returns(int) {
    if(msg.sender != owner) {
      Error("User not authorized")
      return -1111;  // some error code
    }
    // sender is authorized so do stuff
  }
}

Events can't be accessed by contracts so the error message is more for the frontend. If the message is just for the frontend, consider using a pattern of eth_call before an eth_sendTransaction (call vs sendTx explained here).

The eth_call before eth_sendTransaction pattern would look like this frontend Javascript code:

// `contract` is an instance, from web3.eth.contract(...).at(...)

if (contract.foo.call({from: eth.accounts[0]...) === -1111) {
  // example only of how error could be dealt with
  alert("User not authorized");  
  return;
}

// user should now be authorized (though it is possible another transaction may have changed `owner` in contract `C` after above eth_call and before this upcoming eth_sendTransaction)
contract.foo.sendTransaction({from: eth.accounts[0]......)

That said, there can be cases where creating an Error event is desired. For example, if your DApp wants analytics on how many errors have been encountered, how many are unauthorized errors, etc an Error event could be the way to go.

EDIT: When https://github.com/ethereum/solidity/issues/1686 is implemented, the example in the question would look like:

require(msg.sender == owner, "User not authorized");
  • Regarding Possible Alternative, the con of that approach is: Caller will need to pay for the unsuccessful transaction. Of course it sometimes would be desired to "charge" Caller and return meaningful status, so it would be a matter of choice. – Lukasz Zuchowski Sep 6 '17 at 17:32
0

I'v noticed handling events through a modifier works pretty simple without throw with the bottom example.

modifier Modifier_Name() {
        if (Some_Check == Bool) {
            Event(Event_Arg_Type);
            Function_Access_Bool = Bool;
        }
        _;
    }

function Function_Name(Function_Args) public
     Modifier_Name()
     returns bool (success) 
     {
      if (Function_Access_Bool == false) {
          return false;
      }
      else
      {
        ...Desired_Code...;
          return true;
      }
  }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.