9

スローを行うSolidityコントラクトの関数があります。例えば。

   function do(x,y)  {
        if ( msg.sender != owner )
            throw;
        // ...
   }

Truffle 環境には、次のようなテスト js があります。

//.... part of a promise chain
       .then(
            function (_bool0) {
                assert.isTrue(_bool0,"whoops - should be true");
                return contract.do( "okdoke" , {from: accounts[1]} );
            }).then(
            function (tx_id) {
                //..
                done();
            }
    // ...

return contract.do() により、スローが発生する条件が発生します。これにより、このテストのTruffle テスト出力で次が生成されます。

Error: VM Exception while executing transaction: invalid JUMP

このようなテストでコントラクト関数からのスローを処理するためのイディオムは何ですか? スローは正しい動作です。

4

5 に答える 5

3

私が思いついたこの問題に対する「最も正しい」解決策は、送信されたすべてのガスが消費されたことを確認することです。 (実際にスローされたエラーを考えると、これを使用していると思います)およびGeth. Geth でスローが発生すると、トランザクションが作成され、すべてのガスが消費されますが、状態の変更は発生しません。TestRPC は実際にエラーをスローします。これはデバッグ目的に役立ちます。

   //Somewhere where global functions can be defined
   function checkAllGasSpent(gasAmount, gasPrice, account, prevBalance){
       var newBalance = web3.eth.getBalance(account);
       assert.equal(prevBalance.minus(newBalance).toNumber(), gasAmount*gasPrice, 'Incorrect amount of gas used');
   }

   function ifUsingTestRPC(){
       return;
   }

   //Some default values for gas
   var gasAmount = 3000000;
   var gasPrice = 20000000000;

   ....

   //Back in your actual test
   it('should fail ', function (done) {
       var prevBalance;

   ....

   .then(function (_bool0) {
        assert.isTrue(_bool0,"whoops - should be true");
        prevBalance = web3.eth.getBalance(accounts[1]);
        return contract.do( "okdoke" , {from: accounts[1], gasPrice:gasPrice, gas:gasAmount } );
        })
    .catch(ifUsingTestRPC)
    .then(function(){
         checkAllGasSpent(gasAmount, gasPrice, accounts[1], prevBalance);
    })
    .then(done)
    .catch(done);

ただし、別のソリューションが表示された場合は、より簡単なソリューションを喜んで実装します。

注意: 誤って有効なトランザクションですべてのガスを消費した場合、これはそれを検出しません。VM 内でのスローのためにガスが消費されたと想定します。

于 2016-04-13T13:18:19.197 に答える
0

みんなに知らせるために、私もこの問題に遭遇し、以下を使用しています:

function getTransactionError(func) {
  return Promise.resolve().then(func)
    .then(function(txid) {
      var tx = web3.eth.getTransaction(txid);
      var txr = web3.eth.getTransactionReceipt(txid);
      if (txr.gasUsed === tx.gas) throw new Error("all gas used");
    })
    .catch(function(err) {
      return err;
    });
}

geth では、トランザクション ID を使用して利用可能なガスと使用済みガスを取得し、すべてのガスが使用された場合はエラーを返します。testrpc では、スローされた例外をキャッチして返すだけです。次のようにテスト内で使用しています。

return getTransactionError(function() {
    return contract.doSomething();
}).then(function(err) {
    assert.isDefined(err, "transaction should have thrown");
});

もちろん、catch を省略することもできます。その場合、Promise がスローされた場合、単にエラーで失敗します。

于 2016-11-02T17:29:23.287 に答える