Solidity

msg.sender.transfer(purchaseExcess);堅固性測試失敗

  • April 12, 2018

msg.sender.transfer(purchaseExcess);在我的 truffle solidity 單元測試中遇到了異常。知道原因嗎?

我的契約程式碼:

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)

交易失敗是因為測試合約沒有支付回退功能來接受超額資金“轉移”。

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


}

引用自:https://ethereum.stackexchange.com/questions/45419