简体   繁体   English

测试松露中的智能合约要求:如果功能不无效,则交易将被还原

[英]Testing Smart contract requires in Truffle: transaction reverted if function isnt void

im trying to test the requires of a Smart Contract using just solidity according to this article: 我正在根据本文尝试仅通过可靠性来测试智能合约的要求:

http://truffleframework.com/tutorials/testing-for-throws-in-solidity-tests http://truffleframework.com/tutorials/testing-for-throws-in-solidity-tests

This is the contract, the throw proxy contract and the test: 这是合同,委托代理合同和测试:

/* Testing with solidity tests. */

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/MyContract.sol";

contract TestMyContract {

function testInitialStoredValue() {
    MyContract mycontract = new MyContract();

    uint expected = 24;

    Assert.equal(mycontract.mynumber(), expected, "First number set should be 24.");
}

function testTheThrow() {
    MyContract mycontract = new MyContract(); 

    ThrowProxy throwproxy = new ThrowProxy(address(mycontract)); 
    uint num = 7;
    MyContract(address(throwproxy)).storeNum(num);

    bool r = throwproxy.execute.gas(200000)(); 

    Assert.isFalse(r, "Should be false because is should throw!");

}

function testNoThrow() {
    MyContract mycontract = new MyContract(); 

    ThrowProxy throwproxy = new ThrowProxy(address(mycontract)); 

    MyContract(address(throwproxy)).storeNum(22);

    bool r = throwproxy.execute.gas(200000)(); 

    Assert.isTrue(r, "Should be true because is should throw!");

}

}

// Proxy contract for testing throws
contract ThrowProxy {
  address public target;
  bytes data;

  function ThrowProxy(address _target) {
    target = _target;
  }

  //prime the data using the fallback function.
  function() {
    data = msg.data;
  }

  function execute() returns (bool) {
    return target.call(data);
  }
}

If i run the tests i get this error: 如果我运行测试,则会收到此错误:

2

If i change the storeNum function to void from 如果我将storeNum函数更改为从

 function storeNum(uint mynum)
        public
        returns (bool)
    {
     require(mynum > 10);
     mynumber = mynum; 
     return true;    
    }

to

 function storeNum(uint mynum)
        public
    {
     require(mynum > 10);
     mynumber = mynum; 
     return true;    
    }

the tests works.. 测试工作..

Any ideas? 有任何想法吗?

Im using Truffle v4.1.11 我正在使用松露v4.1.11

Let's look at your code: 让我们看看您的代码:

function storeNum(uint mynum)
        public
        returns (bool success)
    {
     require(mynum > 10);
     mynumber = mynum; 
     return true;    
    }

By defining returns (bool success) you're saying to the solidity compiler two things: 通过定义returns (bool success)您对Solidity编译器说了两件事:

  • There is a variable named success of the type bool (variable definition) 有一个名为bool类型的success变量(变量定义)。
  • That variable success will be returned by the function (return definition) 该变量成功将由函数返回(返回定义)

But your variable isn't returned after all (your function ends with return true , and that's why you get an InvalidResponse error on your tests. 但是您的变量毕竟不会返回(您的函数以return true结尾,这就是为什么您在测试中收到InvalidResponse错误的原因。

For your code, the most efficient code would be: 对于您的代码,最有效的代码是:

function storeNum(uint mynum)
        public
        returns (bool)    // you should define at least the type
    {
     require(mynum > 10);
     mynumber = mynum; 
     return true;    
    }

As an exercise, a version using the variable success : 作为练习,使用变量success的版本:

function storeNum(uint mynum)
        public
        returns (bool success)
    {
     require(mynum > 10);
     mynumber = mynum; 
     success = true;    // don't need to use return
    }

Hope it helps. 希望能帮助到你。

Well, i have submited an issue into Truffle github and it is still opened, maybe this is related to recent solidity changes: 好吧,我已经向Truffle github提交了一个问题,它仍然是打开的,也许这与最近的更改有关:

https://github.com/trufflesuite/truffle/issues/1001 https://github.com/trufflesuite/truffle/issues/1001

A workarround for now is to wrap the functions into void functions and test if the execution succeeds or not: 现在的一种解决方法是将函数包装到void函数中,并测试执行是否成功:

/*
    Contract wrapper that inherits from MyContract. This contract wraps the calls of non void functions when
    testing for exceptions.

    Why not invoke directly the function?: https://github.com/trufflesuite/truffle/issues/1001
*/

contract MyExposedContract is MyContract() {


    function callStoreNum(uint256 num)  public {
        storeNum(num);
    }

}

Then use that wrapper in your tests: 然后在测试中使用该包装器:

function testTheThrow() {
    MyExposedContract mycontract = new MyExposedContract (); 

    ThrowProxy throwproxy = new ThrowProxy(address(mycontract)); 
    uint num = 7;
    MyExposedContract (address(throwproxy)).callStoreNum(num);

    bool r = throwproxy.execute.gas(200000)(); 

    Assert.isFalse(r, "Should be false because it should throw!");

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM