'Metamask error: Transaction error. exception thrown in contract code
I've been successfully compiled and deployed my smart contract Campaign.sol. All the functions in my contract can run successfully but as I use my javascript file RequestRow.js to call my function finalizeRequest Metamask pops up the error Transaction error. Exception thrown in contract code
I've googled this error and tried to solve my question by this and this. However, they aren't helpful for my error.
Can anyone tells me where did I do wrong in my smart contract. I don't know how to solve it. Please help!
My Campaign.sol file
pragma solidity ^0.4.17;
contract CampaignFactory{
address[] public deployedCampaigns;
function createCampaign(uint minimum)public{
address newCampaign = new Campaign(minimum, msg.sender);
deployedCampaigns.push(newCampaign);
}
function getDeployedCampaign() public view returns(address[]){
return deployedCampaigns;
}
}
contract Campaign{
struct Request {
string description;
uint value;
address recipient;
bool complete;
uint approvalCount;
mapping(address => bool) approvals;
}
Request[] public requests;
address public manager;
uint public minimumContribution;
mapping (address => bool) public approvers;
uint public approversCount;
modifier restricted(){
require(msg.sender == manager);
_;
}
function Campaign (uint minimum, address creator)public{
manager = creator;
minimumContribution = minimum;
}
function contribue()public payable{
require(msg.value > minimumContribution);
approvers[msg.sender] = true;
approversCount++;
}
function createRequest(string description, uint value, address recipient)public restricted{
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;
}
function getSummary() public view returns (
uint, uint, uint, uint, address
){
return (
minimumContribution,
this.balance,
requests.length,
approversCount,
manager
);
}
function getRequestsCount() public view returns (uint){
return requests.length;
}
}
My RequestRow.js file
import React, {Component} from 'react';
import {Table, Button} from 'semantic-ui-react';
import web3 from '../ethereum/web3';
import Campaign from '../ethereum/campaign';
class RequestRow extends Component{
onApprove = async() => {
const campaign = Campaign(this.props.address);
const accounts = await web3.eth.getAccounts();
await campaign.methods.approveRequest(this.props.id).send({
from: accounts[0]
});
};
onFinalize = async() => {
const campaign = Campaign(this.props.address);
const accounts = await web3.eth.getAccounts();
await campaign.methods.finalizeRequest(this.props.id).send({
from: accounts[0]
});
};
render(){
const {Row, Cell} = Table;
const {id, request, approversCount} = this.props;
return (
<Row>
<Cell>{id}</Cell>
<Cell>{request.description}</Cell>
<Cell>{web3.utils.fromWei(request.value,'ether')}</Cell>
<Cell>{request.recipient}</Cell>
<Cell>{request.approvalCount}/{approversCount}</Cell>
<Cell>
<Button color="green" basic onClick={this.onApprove}>
Approve
</Button>
</Cell>
<Cell>
<Button color="teal" basic onClick={this.onFinalize}>
Finalize
</Button>
</Cell>
</Row>
)
}
}
export default RequestRow;
The full error message that I got in the deveoper console
Uncaught (in promise) Error: Transaction has been reverted by the EVM:
{
"blockHash": "0xcca9f6dac8c99c2ecc1f9314661399bda3a6096bf0f36d1c1724d84dcece42b2",
"blockNumber": 5145820,
"contractAddress": null,
"cumulativeGasUsed": 270372,
"from": "0x284aea2dca83c9c6247907554cb27120f7ce1892",
"gasUsed": 55899,
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": false,
"to": "0x6ff70b2a9c30909431714902581539087fe25a3b",
"transactionHash": "0x24b15e5db8bb673375409327cdde0fba98844126f5909ed7681845ee3bccce84",
"transactionIndex": 2,
"events": {}
}
at index.js?959bf61:366
Solution 1:[1]
This error is due to the rather complicated account switching required.
First, you need to create a campaign with one of your MetaMask accounts, Then you need to create a request while in this same account as 'manager'. When you copy and paste the address of the recipient make sure to switch back to the right account after, before submitting the request.
Then you need to contribute to the campaign with another MetaMask account, and approve the request while making sure you are still in the account that you contributed the funds with.
Normally this account switching would not be an issue but it is simulating multiple different users interacting with the contract.
Regards
Mark
Solution 2:[2]
you need use truffle/HDwallet and set provider.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |
