Solidity

從 React 呼叫智能合約函式

  • September 1, 2022

我正在從 React 呼叫 Solidity 中的智能合約功能,它應該計算特定選擇的票數。當我從松露控制台呼叫該函式時,該函式執行良好。但是,當我從 React 應用程序呼叫它時,該函式被執行但投票不計算在內。

功能:

function doVote(uint _choice)
       public
       inState(State.Voting)
       returns(bool voted)
   {
       bool found = false;        
       
       if(!voterRegister[msg.sender].voted ){
           voterRegister[msg.sender].voted = true;
           vote memory v;
           v.voterAddress = msg.sender;
           v.choice = _choice;

           
           candidatesRegister[_choice].votes++  ;
           
           votes[totalVote] = v;
           totalVote++;
           found = true;
       }
       return found;        
   }

在松露控制台中,這有效:

> ballot = await Ballot.deployed()
> ballot.doVote(1)

在 React 中,我有這個函式,其中地址代表登錄到應用程序的使用者的公鑰:

export const doVote = async (choice, address)=> {


   web3.eth.defaultAccount = address;
   console.log("network: " + Contract.networks[networkID].address)
   const BallotContract = new web3.eth.Contract(Contract.abi, Contract.networks[networkID].address);       

   return await BallotContract.methods
   .doVote(choice)

};

如果我將 .call() 添加到 .doVote(choice) 函式將返回“true”

當您執行.call()時,區塊鏈的狀態不會改變。根據 web3 文件:

methods.myMethod.call

Will call a “constant” method and execute its smart contract method in the EVM without sending any transaction. Note calling cannot alter the smart contract state.

呼叫對於模擬交易並獲取其返回值很有用,您將其視為“真”,但由於區塊鏈的狀態沒有改變,您的投票不會被計算在內。

你真正想做的是使用.send()

methods.myMethod.send
Will send a transaction to the smart contract and execute its method. Note this can alter the smart contract state.

假設您的瀏覽器中有元遮罩,則此解決方案與 ethers 一起使用:

我也使用了 react,我將合約 abi 和地址儲存在 json 中

import smartContract from './smart-contract-abi.json';
import contractAddress from './contract-address.json';
import { ethers } from 'ethers';

// step 1 - Connect wallet

await window.ethereum.request({method: 'eth_requestAccounts'});

// step 2 - Initialize your contract

   this.provider = new ethers.providers.Web3Provider(window.ethereum);
   this.yourSignedContractObject = new ethers.Contract(
     contractAddress.Address, 
     smartContract.Abi,
     this.provider.getSigner(0)
   );

// step 3 - Submit transaction to metamask

   const tx = await this.yourSignedContractObject.doVote(yourChoice)

來源:(檢查 typescript PR) https://github.com/NomicFoundation/hardhat-boilerplate

引用自:https://ethereum.stackexchange.com/questions/134754