fluttersoliditysmartcontractsremixdecentralized-applications

gas estimation error occured while creating multipple contracts


I am working on a college project to make an election dapp using smart contracts. I coded the smart contract(Election) and it worked fine until I included one more contract(ElectionFactory) to get multiple elections. I got the error when I executed the function createElection(on the Election factory contract)

error:

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

smart contract :

//SPDX-License-Identifier: UNLICENSED
pragma solidity >= 0.8.0<0.9.0;

contract ElectionFactory{
    address[]public deployedElections;
    uint public electionscount;
    address public owner;


    modifier ownerOnly{
        require(msg.sender == owner);
        _;
    }

    function createElection(string memory _elecname,uint128 _enddate)public ownerOnly{
       // Election newElection = new Election(_elecname,_enddate);
       Election newElection = new Election();
        deployedElections.push(address(newElection));
        newElection.startElection(_elecname,_enddate);
        electionscount++;
    }

    function getDeployedElection(uint index)public view returns(address){ //less gas function
        return deployedElections[index];
    }

    function getElectionCounts()public view returns(uint){ // less gas function
        return electionscount;
    }

    // function removeElection(uint index)public{  //function not developed yet
    //     delete deployedElections[index];
    // }
}

//contract for election
contract Election{

    //candidatte  name,numvotes
    struct Candidate{
        string name; 
        uint numVotes; 
    }
    
    //voter name,authorised,whom(voting to),voted(or not)
    struct Voter{
        string name; 
        bool authorised; 
        uint whom;
        bool voted; 
    }

    //constructor and variables
    uint128 enddate;
    // constructor(string memory _elecname,uint _enddate){
    //     startElection(_elecname,_enddate);
    // }


    address public owner;  //is the admin starts election
    string public electionName;  //the name of the election
    bool public electionstatus = true;//know if election is close or not if cloded status=false
    bool public electionStarted = false;  //election started or not

    mapping(address => Voter) public voters; // voters = i.voter[adres]
    Candidate[] public candidates; //array of candidate 
    uint public totalVotes; //total votes voted 

//modifiers to limit or require
    modifier ownerOnly(){ 
        require(msg.sender == owner); 
        _;
    }
    modifier ifnoElection(){ 
        require(electionstatus==true);
        require(electionStarted==false); 
        _;
    }
    
    //function to start election
    function startElection(string memory _electionName,uint128 _enddate)ifnoElection public{ 
        require(_enddate>block.timestamp);
        owner = msg.sender; 
        electionName = _electionName; 
        electionStarted = true;

    }

    //adding candidate only admin candidate(name, number of votes)
    function addCandidate(string memory _candidateName)ownerOnly public{ 
        candidates.push(Candidate(_candidateName, 0));
    }

    //authorize voter admin only can authorize voter needs voter adress
    function authorizeVoter(address _voterAddress) ownerOnly public{ 
        voters[_voterAddress].authorised= true; 
    }

    //function to get total candidates number
    function getNumCandidates() public view returns(uint){ 
        return candidates.length; 
    }

    //function to vote requires the index of candidate to vote
    function vote(uint candidateIndex)ifnoElection public{ 
        require(!voters[msg.sender].voted); 
        require(voters[msg.sender].authorised); 
        voters[msg.sender].whom = candidateIndex; 
        voters[msg.sender].voted = true; 

        candidates[candidateIndex].numVotes++; 
        totalVotes++;
    }

    //to get total votes
    function getTotalVotes()public view returns(uint) {
        return totalVotes;
    }

    //get info of candidate 
    function candidateInfo(uint index) public view returns(Candidate memory){ 
        return candidates[index];
    }

    // function closeElection()public {
    //     //remove();
    //     electionStarted = false;
    //     electionstatus = false;
    // }

    // function remove() public ownerOnly{
    //     address one = 0xc4d9eE2d363b465443D751F7D553919281D1bd0a;
    //     address two = 0x2f8434dA7347C7c5266eDcCf9C36D33aa7D59dD4;
    //     address three = 0x6435Fdf5B2888A81C08c6dF5e4AF3F2580744e0F;
    //     delete voters[one];
    //     delete voters[two];
    //     delete voters[three];
    //     uint n = candidates.length;
    //     for(uint i=0;i<n;i++){
    //         delete candidates[i];
    //     }

    // // Reset the value to the default value.
    // //delete playerTicket[_addr];
    // }
    
}

if you are kind enough please suggest some resources for me to do this project with less gas price


Solution

  • the error is because of the modifier. add an error message "Invalid caller" for the revert reason, you will see why it is reverted

    modifier ownerOnly{
            require(msg.sender == owner,"Invalid caller");
            _;
        }
    

    because the callee of the createElection is not the one who created the ElectionFactory contract, the callee is the ElectionFactory contract. you can use tx.origin==owner inside modifier but this has security flaws.

    `msg.sender` preferred over `tx.origin` in Solidity