首页 > 解决方案 > 执行智能合约时的 Solidity 错误消息:“如果您发送值,则应支付构造函数”

问题描述

我正在尝试通过编写下面的智能合约来学习可靠性(见下面的片段)。我已经能够成功编译(即没有错误)智能合约,其目的是将继承从一个以太坊钱包地址支付给另一个(例如家庭成员)。我也能够部署它,但是当我尝试将继承权转移给收款人时,我收到以下错误消息(另见附图)。任何帮助是极大的赞赏 !

错误消息:“交易到 Will.setInheritance 错误:VM 错误:revert。revert 交易已恢复到初始状态。注意:如果您发送值,则应支付构造函数。调试交易以获取更多信息”

pragma solidity ^0.5.1;

//Use a double forward slash to write a like this one
// Line1 : First we nominate which version of the SOLIDITY code we are using.
//This is always the first step in our code.
// Here we tell REMIX that the the source code we are using is version 0.5.1 or above (by using the ^ - carrot symbol)

// We will start building our SC which will eventually split the inheritance of a persons will (e.g. Grandfather) amongst the Family members


contract Will {
//Line 9 : Each new contract must be named as  “contract”, then the name with the first letter always CAPITALIZED, followed by open/close curly brackets to contain the logic. 


    address owner;
    uint fortune;
    bool isDeceased;

// Line 13: here we declare the variables of the smart contract - each variable must be listed along with its variable type in SOLIDITY
// Line 13: owner is of the address type of variable in SOLIDITY (unique variable in SOLIDITY - refers to an ethereum network address)
// Line 14: fortune is of the type uint (unsigned integer = a positive only integer)
// Line 15: isDeceased is a boolean variable (i.e. TRUE or FALSE type)

    constructor() public payable {
        owner = msg.sender;
        fortune = msg.value;
        isDeceased = false;
    }
    

// Line 22: here we use a constructor function to set these values in he contract
// The “public” keyword is what’s known as a “visibility modifier” which tells the contract who is allowed to call the function. 
// Public means that the function can be called within the contract and outside of it by someone else or another contract.
// The “payable” keyword allows the function to send and receive ether. 
// When we deploy the contract we can initialize it with an ether balance. 
// When the contract receives ether, it will store it in its own address.
// Then we will use the SC to transfer the ether to another adress (or inheritor)
// Line 23:  we set the owner to “msg.sender”, which is a built-in global variable representative of the address that is calling the function. 
//In this case, it will be the owner of the funds.
// Line 24: The fortune is set to “msg.value”, which is another built-in variable that tells us how much ether has been sent.
// Line 25: We set the isDeceased to false 
    
    modifier onlyOwner {
        require (msg.sender ==owner);
        _;
    }

        
    modifier mustBeDeceased {
        require (isDeceased == true);
        _;
    }
    
// Modifiers are add-ons to functions that contain conditional logic. 
// Line 41 declares “onlyOwner” modifier. 
// If added to a function, it can only be called if the caller (msg.sender) is equivalent to the owner variable as stated above (remember how we set the owner in the constructor). We will need this to allow the distribution of funds, which will be implemented later.
// The “require” keyword states that we want isDeceased to be true otherwise solidity will throw an error and the execution will stop. 
// The “_;” at the end tells the execution to shift to the actual function after it’s done reading the modifier.


// Now we must declare how the inheritance is divided amongst the family members. 
// We will need their public wallet keys (addresses) and their desired allotments.
// First we create a list to store the wallet addresses (of the family members) 
// And we create a and a function that sets the inheritance for each address.
    
    
    address payable[] wallets;
    
    //ABOVE WE HAVE TO ENTER payable to tell SOLIDITY that the address for the payout of the money is the wallet address
    // function will not work without adding "address" here 
    
    mapping (address => uint) inheritance;
    
    function setInheritance(address payable _wallet, uint _inheritance) public onlyOwner {
        wallets.push(_wallet);
        inheritance [_wallet] = _inheritance;
    }
    
    
// Line 67: declares an empty array called “wallets” for storing the family members’ wallet addresses. 
// This is a list-like data structure . The square brackets after “address” indicate it’s an array of items rather than a single variable.
// Line 69: Creates a mapping from an address type to a uint type named “inheritance” 
// We will use this for distributing the inheritance to a family members wallet (It’s the equivalent of a “dictionary” in other languages such as Python and Javascript, Key/Value Pair).
    
// Line 71 declares the function that adds an address to the (empty) inheritance array we just created and then sets the inheritance to be provided to this address. 
// We added the the “onlyOwner” modifier we added to this function, which means that only the owner of the money can distribute the funds 

// Finally we create the payout function, i.e. the actual transfer of the funds

    function payout() private mustBeDeceased {
        for (uint i=0; i<wallets.length; i++) {
            wallets[i].transfer(inheritance[wallets[i]]);
        }
    }
    
    function deceased() public payable onlyOwner {
        isDeceased = true;
        payout();
    }
}

当我尝试将付款转移给收款人时收到的 Solidity 错误消息

标签: ethereumsoliditysmartcontracts

解决方案


我执行了您的代码并进行了深入检查。请注意,当前 remix 和solidity 没有显示好的和有意义的错误消息。

这里的问题是您的构造函数是应付的:

constructor() public payable {
        owner = msg.sender;
        fortune = msg.value;
        isDeceased = false;
    }

如果你在constructor没有任何值的情况下执行,它也会setInheritance执行而不会出错,当你尝试运行deceased另一个应付函数的函数时,事情就会爆炸。混音会说构造函数是应付的,但没有发送任何值。

如果您想value运行任何payable function. 在这里,您可以为应付函数编写值。 在此处输入图像描述

希望能帮助到你。


推荐阅读