1

I'm stuck at sending a signed transaction to a Smart Contract deployed on Ropsten network.

As learning purposes, I created a 'Voting' smart contract. This contract includes 2 candidates we can vote for. A user can only sign once. The contract has been deployed and tested on Ropsten. It works great, if I use only Web3 (ie I'm providing manually my Private Key).

Now, I would like the user to identify himself, then sign the vote. Here I'm stuck.

Using Vue, I have 2 main methods:

Method 1: Enable metamask

this.provider = await detectEthereumProvider();

    if (this.provider) {

      const accounts = await this.provider.request(
         {
              method: 'eth_requestAccounts'
          }
      );

      this.account = accounts[0];

    } else {

      console.log('Please install MetaMask!');

    }

Method 2: Send a signed Vote (here I'm stuck) --> partial code

  const ropsten = 'https://ropsten.infura.io/v3/MY_KEY';

  const web3 = new Web3(ropsten);

  const contract = new web3.eth.Contract(
                        Election.abi, 
                        this.params.to
                        );
  [??????????????]

  try {

    const txHash = await this.provider.request({
      method: 'eth_sendTransaction',
      params: [
        {
          from: this.account,
          to: this.contractAddress,
          data: ??????????????
        }
      ],
    });

    console.log(txHash);

  } catch (error) {

    console.log(error);
    
  }
}

If I understand well, now I have to create data parameter which a Hex of my function to vote.

Here is the function to vote I would use

const vote = await contract.methods.vote(1).send({
               from: ...
               to: ...
               });

Here I'm lost, I don't know how to proceed properly.

Expected output:

  • First, the user enable Metamask,
  • Second, the use vote for the candidate 1 or 2
  • Before sending the transaction to Ropsten, Metamask requests to sign the transaction

For information, here my Election.sol smart contract :

pragma solidity >=0.4.21 <0.7.0;

contract Election {

    //Model Candidate
    struct Candidate {
        uint id;
        string name;
        uint voteCount;
    }

    mapping(uint => Candidate) public candidates;
    //store accounts that have voted
    mapping(address => bool) public voters;

    uint public candidatesCount;

    event votedEvent (
        uint indexed _candidateId
    );

    constructor() public {
        addCandidate("Barack Obama");
        addCandidate("Donald Trump");
    }

    function addCandidate(string memory _name) private {
        candidatesCount ++;
        candidates[candidatesCount] = Candidate(candidatesCount, _name, 0);
    }

    function vote(uint _candidateId) public {
        //not voted yet
        require(!voters[msg.sender]);

        //valid vandidate
        require(_candidateId > 0 && _candidateId <= candidatesCount);

        //record vote
        voters[msg.sender] = true;

        //update candidate vote count
        candidates[_candidateId].voteCount ++;

        //voted event
        emit votedEvent(_candidateId);
    }

}

Your help is more then welcome! Thanks in advance!

1 Answer 1

3

Since you created a contract instance, you can use it have Metamask format the transaction and send sign request to user.

Try replacing this:

const txHash = await this.provider.request({
  method: 'eth_sendTransaction',
  params: [
    {
      from: this.account,
      to: this.contractAddress,
      data: ??????????????
    }
  ],
})

With this:

contract.methods.vote(1).send({
           from: accounts[0]
           
           });

You should see a Metamask request to sign Tx.

3
  • 1
    Thank you. I just tried replacing what you said, but I got the following error message: The method eth_sendTransaction does not exist/is not available
    – Henri
    Aug 29, 2021 at 11:11
  • 2
    This is likely because you're connected to Infura node which does not support signed transactions. You need to set your web3 provider to Metamask provider. Try using const web3 = new Web3(window.ethereum) as provider instead.
    – Bigbrotha
    Aug 29, 2021 at 11:25
  • 1
    It works ! Thanks a lot. The problem was that I was using infura myself.. Thank you very much for your help !
    – Henri
    Aug 29, 2021 at 11:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.