Является ли хорошей практикой регистрировать событие каждый раз, когда я запускаю Solidity?

Я знаю, что в Solidity (0.3.2) нет возможности создавать определенные исключения. (Все является invalid JUMPошибкой.) Представляется полезным иметь способ регистрации определенных ошибок. Имеет ли смысл создавать событие Error, которое будет запускаться перед любым исключением? Есть ли недостатки, о которых я не думаю?

event Error(string message);

...

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

РЕДАКТИРОВАТЬ: похоже, что событие вообще не регистрируется, если транзакция не удалась. Кто-нибудь может подтвердить?

Ответы (2)

За исключением, как и в случае throw, все эффекты (включая события) транзакции отменяются, кроме выплаты майнеру. Таким образом, было бы бесполезно запускать событие перед throw.


Возможная альтернатива

Если полный реверс через исключение не требуется , можно использовать код ошибки.

Пример:

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

Контракты не могут получить доступ к событиям, поэтому сообщение об ошибке больше для внешнего интерфейса. Если сообщение предназначено только для внешнего интерфейса, рассмотрите возможность использования шаблона eth_callперед eth_sendTransaction (здесь объясняется call vs sendTx).

Шаблон « eth_callдо eth_sendTransaction» будет выглядеть следующим образом:

// `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]......)

Тем не менее, могут быть случаи, когда желательно создать событие Error. Например, если вашему DApp требуется аналитика о том, сколько ошибок было обнаружено, сколько несанкционированных ошибок и т. д., может подойти событие Error.

EDIT: когда https://github.com/ethereum/solidity/issues/1686 реализован, пример в вопросе будет выглядеть так:

require(msg.sender == owner, "User not authorized");
Что касается « Возможной альтернативы », то минус этого подхода: вызывающему абоненту нужно будет заплатить за неудачную транзакцию. Конечно, иногда было бы желательно «зарядить» вызывающего абонента и вернуть осмысленный статус, так что это был бы вопрос выбора.

Я заметил, что обработка событий с помощью модификатора работает довольно просто без броска в нижнем примере.

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