Obtuve una excepción en la línea msg.sender.transfer(purchaseExcess);
en mi prueba de unidad de solidez de trufa. ¿Alguna idea del motivo?
mi código de contrato:
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);
}
código de pruebas unitarias:
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);
}
}
mensaje de error
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)
La transacción está fallando porque el contrato de prueba no tiene una función de reserva pagadera para aceptar la "transferencia" de fondos en exceso .
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 { }
}
Se agregaron dos pruebas de afirmación (algunos podrían argumentar que esta no es la mejor práctica al tener más de una afirmación en la misma prueba)
Además, se tuvo que implementar un contrato de EmojiCoin muy básico para comprobar que este era el problema:
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);
}
}
mirg
mirg
uint public initialBalance = 2 ether;
podría resolver el problema.Wenjing