为什么会出现此错误?“气体估算值因以下消息而出错(请参阅下文).交易>执行可能会失败"

问题描述:

尝试使用Remix IDE测试坚固性.我不断收到错误消息:

Trying to test solidity using Remix IDE. I keep getting the error:

气体估计错误,并显示以下消息(请参阅下文).事务>执行可能会失败.您要强制发送吗?

Gas estimation errored with the following message (see below). The transaction > execution will likely fail. Do you want to force sending?

有人知道什么可能给我这个错误.我正在尝试使用以太坊智能合约来销售产品.我已使用Remix IDE创建了值为0的合同.我可以成功创建合同和add_product,但无法购买.最后一行给了我上面提到的错误.

Does anybody have an idea about what might be giving me this error. It I am trying to sell products using the ethereum smart contracts. I have used the Remix IDE to create this contract with value = 0. I am successfully able to create the contract and add_product but I am unable to Buy. The last line give me the error mentionned above.

我再次测试的可靠性文件如下:如您所见,我创建了一个卖出合约,该合约允许用户使用区块链出售产品,而买方则可以获取以太坊支付价格的产品.如果有人对我有更好的解决方案来使用此确切用例,那么我欢迎您提出建议.

The solidity file I am testing againt is the following: As you can see I create a Sell contract which would allow a user to sell products using the blockchain and a buyer to retrieve the product paying the price in ethereum. If anyone has a better solution for me to use for this exact use-case I am opened to suggestions.

pragma solidity ^0.4.0;

contract Sell {

    struct Product_Quantity{
        string _product_name;  
        uint256 _product_quantity;        
        uint256 _price_unity; 
        bool isValue;
    }
    struct Seller{
        address _id;
        mapping(string => Product_Quantity) products; 

    }

    Seller public seller;
    mapping (address => Product_Quantity) product_owners;

    function Sell(){
        seller._id = msg.sender;
    }
    function add_product(string product_name, uint256 product_quantity, uint256 price_unity) {        
        if(msg.sender != seller._id) throw;
        if(seller.products[product_name].isValue){
            seller.products[product_name]._product_quantity += product_quantity;
        }
        else{
            seller.products[product_name] = Product_Quantity(product_name, product_quantity, price_unity, true); 
        }
    }

    function Buy( string product_name, uint256 quantity) payable {


        if(product_owners[msg.sender].isValue){
            product_owners[msg.sender]._product_quantity += quantity; 
        }
        else{
            product_owners[msg.sender] = Product_Quantity(product_name, quantity, seller.products[product_name]._price_unity, true);

        }
        seller.products[product_name]._product_quantity -= quantity;
        seller._id.transfer(seller.products[product_name]._price_unity * quantity);


    }
}

这是非常通用的Remix错误消息.幸运的是,今天我在Remix上看到了新的错误消息(很好的更新专家!),这使调试问题变得更加容易.

That's a very generic Remix error message. Fortunately, today I'm seeing new error messages on Remix (nice update guys!), which makes it easier to debug the problem.

当某人试图购买某种产品时,您应该检查传递的价值(以wei为单位)是否是购买该产品和数量的正确金额.

When someone tries to buy a product, you should check if the value passed (in wei) is the right amount to buy that product and quantity.

由于您没有进行检查,因此买方可以购买amou​​t等于0的产品,这意味着在buy()函数结束时,合同将无权发送给卖方.这将引发异常,并且交易将被还原.

Since you're not checking that, a buyer can buy a product with an amout equals to 0, which means the contract will have no wei to send to the seller at the end of the buy() function. That will throw an exception and the transaction will be reverted.

我将您的代码更新为在Solidity 0.4.23(最新版本)上运行,进行了一些代码重构,并在buy()函数中添加了一个修饰符,以检查传递的金额是否正确.

I updated your code to run on solidity 0.4.23 (latest version), made some code refactoring and add a modifier to the buy() function to check if the amount passed is correct.

pragma solidity ^0.4.23;

contract Sell {

    struct Product_Quantity{
        string _product_name;  
        uint256 _product_quantity;        
        uint256 _price_unity; 
        bool isValue;
    }

    mapping (address => Product_Quantity) product_owners;

    struct Seller{
        address _id;
        mapping(string => Product_Quantity) products;
    }

    Seller public seller;

    constructor() public {
        seller._id = msg.sender;
    }

    function add_product (string product_name, uint256 product_quantity, uint256 price_unity) public {        
        require(msg.sender == seller._id);
        if (seller.products[product_name].isValue) {
            seller.products[product_name]._product_quantity += product_quantity;
        }
        else{
            seller.products[product_name] = Product_Quantity(product_name, product_quantity, price_unity, true); 
        }
    }

    modifier hasEnoughEther (string product_name, uint256 quantity) {
        require (seller.products[product_name].isValue);  // does the product exists?
        uint256 neededEther = seller.products[product_name]._price_unity * quantity;
        require (msg.value == neededEther);  // did the buyer sent the correct value?
        _;
    }

    function buy (string product_name, uint256 quantity) payable public hasEnoughEther (product_name, quantity) {
        if (product_owners[msg.sender].isValue) {
            product_owners[msg.sender]._product_quantity += quantity; 
        } else {
            product_owners[msg.sender] = Product_Quantity(product_name, quantity, seller.products[product_name]._price_unity, true);
        }
        seller.products[product_name]._product_quantity -= quantity;
        seller._id.transfer(seller.products[product_name]._price_unity * quantity);
    }
}