msg.sender.transfer (покупкаExcess); провал в тесте на прочность

Получил исключение на линии msg.sender.transfer(purchaseExcess);в моем модульном тесте на прочность трюфелей. Есть идеи, в чем причина?

мой код контракта:

function purchase(uint256 _tokenId) public payable {
    address oldOwner = tokenOwner[_tokenId];
    uint256 sellingPrice = emojiIndexToPrice[_tokenId];
    address newOwner = msg.sender;

    require(oldOwner != newOwner);

    require(newOwner != address(0));

    require(msg.value >= sellingPrice);

    uint256 percentage = SafeMath.sub(100, ownerCut);
    uint256 payment = uint256(SafeMath.div(SafeMath.mul(sellingPrice, percentage), 100));
    uint256 purchaseExcess = SafeMath.sub(msg.value, sellingPrice);

    emojiIndexToPrice[_tokenId] = SafeMath.div(SafeMath.mul(sellingPrice, 150), percentage);

    _transfer(oldOwner, newOwner, _tokenId);

    if (oldOwner != address(this)) {
      oldOwner.transfer(payment);
    }

    msg.sender.transfer(purchaseExcess);
}

код модульных тестов:

contract TestEmojiCoin {
    uint public initialBalance = 1 ether;

    function testPurchase() public {
        address contractAddress = DeployedAddresses.EmojiCoin();
        EmojiCoin emojiCoin = EmojiCoin(contractAddress);

        // Emoji 0 is created in previous test.

        emojiCoin.purchase.value(1 ether).gas(30000000000)(0);      
    }
}

сообщение об ошибке

     Error: VM Exception while processing transaction: revert
  at Object.InvalidResponse (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/errors.js:38:1)
  at /usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/requestmanager.js:86:1
  at /usr/local/lib/node_modules/truffle/build/webpack:/~/truffle-provider/wrapper.js:134:1
  at XMLHttpRequest.request.onreadystatechange (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/httpprovider.js:128:1)
  at XMLHttpRequestEventTarget.dispatchEvent (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:64:1)
  at XMLHttpRequest._setReadyState (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:354:1)
  at XMLHttpRequest._onHttpResponseEnd (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:509:1)
  at IncomingMessage.<anonymous> (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:469:1)
  at endReadableNT (_stream_readable.js:1101:12)
  at process._tickCallback (internal/process/next_tick.js:114:19)
какую ошибку вы получаете?
Я не совсем уверен, но вам может потребоваться увеличить баланс контракта, если для транзакции требуется газ. uint public initialBalance = 2 ether;может решить проблему.
@mirg, к сожалению, это не решило проблему :-(

Ответы (1)

Транзакция завершается со сбоем, потому что тестовый контракт не имеет оплачиваемой резервной функции для принятия «перевода» избыточных средств .

pragma solidity ^0.4.17;

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

contract TestEmojiCoin {
    uint public initialBalance = 1 ether;

    function testPurchase() public {
        address contractAddress = DeployedAddresses.EmojiCoin();
        EmojiCoin emojiCoin = EmojiCoin(contractAddress);

        // Emoji 0 is created in previous test.

        address owner_0 = emojiCoin.tokenOwner(0);
        Assert.notEqual( owner_0, this, "owner for coin 0 is incorrect" );

        emojiCoin.purchase.value(1 ether).gas(30000000000)(0);

        owner_0 = emojiCoin.tokenOwner(0);
        Assert.equal( owner_0, this, "owner for coin 0 is incorrect" );
    }

    // this new function IS REQUIRED for the test to work
    function() public payable { }

}

Добавлены два теста утверждений (некоторые могут возразить, что это не лучшая практика, заключающаяся в наличии более одного утверждения в одном тесте).

Кроме того, необходимо было реализовать очень простой контракт EmojiCoin, чтобы убедиться, что это проблема:

pragma solidity ^0.4.17;

import "zeppelin-solidity/contracts/math/SafeMath.sol";

contract EmojiCoin {

    mapping(uint256 => address) public tokenOwner;
    mapping(uint256 => uint256) public emojiIndexToPrice;
    uint256 public ownerCut  = 5;


    function EmojiCoin() public {

        // very simple constructor for the purpose of testing only
        tokenOwner[0] = msg.sender;
        emojiIndexToPrice[0] = 1 ether;

    }

    // simple _transfer implementation for the purpose of testing only
    function _transfer(address oldOwner, address newOwner, uint256 _tokenId) internal {
        require(tokenOwner[_tokenId] == oldOwner);
        tokenOwner[_tokenId] = newOwner;
    }

    function purchase(uint256 _tokenId) public payable {
        address oldOwner = tokenOwner[_tokenId];
        uint256 sellingPrice = emojiIndexToPrice[_tokenId];
        address newOwner = msg.sender;

        require(oldOwner != newOwner);

        require(newOwner != address(0));

        require(msg.value >= sellingPrice);

        uint256 percentage = SafeMath.sub(100, ownerCut);
        uint256 payment = uint256(SafeMath.div(SafeMath.mul(sellingPrice, percentage), 100));
        uint256 purchaseExcess = SafeMath.sub(msg.value, sellingPrice);

        emojiIndexToPrice[_tokenId] = SafeMath.div(SafeMath.mul(sellingPrice, 150), percentage);

        _transfer(oldOwner, newOwner, _tokenId);

        if (oldOwner != address(this)) {
           oldOwner.transfer(payment);
        }

        msg.sender.transfer(purchaseExcess);
    }


}
Большое спасибо! не могли бы вы подробнее рассказать о том, что «любой из переводов может завершиться неудачей и привести к задержке эфира в контракте»
Мой последний комментарий был необоснованным и был удален; было поздно, и я думал о невозможном кодовом пути.