Search code examples
ethereumsolidityweb3js

How to resolve this error in solidity "The constructor should be payable if you send value."?


In this solidity code the finalizeRequest() is giving a run-time error. Here is the error :

Campaign.finalizeRequest(uint256) 0x692...77b3a

transact to Campaign.finalizeRequest errored: VM error: revert.
revert  The transaction has been reverted to the initial state.
Note: The constructor should be payable if you send value.  Debug the transaction to get more information.

Here is the code:

pragma solidity ^0.4.17;

contract Campaign {
    struct Request {
        string description;
        uint value;
        address  recipient;
        bool complete;
        uint approvalCount;
        mapping (address => bool) approvals;
    }

    address public manager;
    uint public minimumContribution;
    // address[] public approvers;
    mapping (address => bool) public approvers;
    Request[] public requests;
    uint public approversCount;


    function Campaign(uint minimum) public {
        manager=msg.sender;
        minimumContribution=minimum;
    }

    function contribute() public payable {
        require(msg.value>minimumContribution);
        // approvers.push(msg.sender);
        approvers[msg.sender]=true;
        approversCount++;
    }

    function createRequest(string description,uint value,address  recipient) public restricted {
        // require (approvers[msg.sender]);    
        Request memory newRequest=Request({description:description,value:value,recipient:recipient,complete:false,approvalCount:0});
        requests.push(newRequest);

    }

    function approveRequest(uint index) public {
        Request storage request=requests[index];

        require(approvers[msg.sender]);
        require(!request.approvals[msg.sender]);
        request.approvals[msg.sender]=true;
        request.approvalCount++;
    } 

    function finalizeRequest(uint index) public restricted {
        Request storage request = requests[index];

        require(request.approvalCount>=(approversCount/2));
        require(!request.complete);
        request.recipient.transfer(request.value);
        request.complete=true;

    } 

    modifier restricted() {
        require (msg.sender == manager);
        _;
    }
}

As far as I could debug, when I comment out request.recipient.transfer(request.value); in the finalizeRequest() function no runtime error is thrown. So error seems to be in this line of code.


Solution

  • As far as i see your finalizeRequest() function consists transfer of ether as defined request.recipient.transfer(request.value); so you need to make your finalizeRequest() as payable.

    replace finalizeRequest() with:

    function finalizeRequest(uint index) public restricted payable {
        Request storage request = requests[index];
        require(request.approvalCount>=(approversCount/2));
        require(!request.complete);
        request.recipient.transfer(request.value);
        request.complete=true;
    } 
    

    Thumb Rule: Whenever you are sending or receiving ether in any function, mark it as payable.

    Reason why you need payable keyword is well explained here.