错误:无法估计gas;交易可能会失败或者可能需要在 React 项目中手动限制 Gas

问题描述 投票:0回答:1

我已经在 remix 中创建了智能合约,一切正常:

//SPDX-License-Identifier: Unlicense

pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;

import "./ReentrancyGuard.sol";
import "./SafeMath.sol";
import "./Ownable.sol";
import "./IERC20.sol";

contract MultiSend is Ownable, ReentrancyGuard {
    using SafeMath for uint256;

    event TokensSent(address token, address sender, uint256 total);
    event TokenReceived(address token, address receiver, uint256 amount);
    event ETHSent(address sender, uint256 total);
    event ETHReceived(address sender, uint256 amount);
    event TokenAddressChanged(address newAddress);

    address public tokenAddress;

    constructor(address _tokenAddress) public {
        tokenAddress = _tokenAddress;
    }

    fallback() external {
        revert();
    }

    function sendToken(
        address _aa,
        address _ba,
        uint256 _av,
        uint256 _bv
    ) public nonReentrant returns (bool) {
        require(_aa != address(0), "please check address");
        require(_ba != address(0), "please check address");
        require(_av > 0, "please check amount");
        require(_bv > 0, "please check amount");
        IERC20 token = IERC20(tokenAddress);
        require(
            token.allowance(msg.sender, address(this)) >= _av + _bv,
            "please check approve"
        );
        token.transferFrom(msg.sender, _aa, _av);
        emit TokenReceived(tokenAddress, _aa, _av);
        token.transferFrom(msg.sender, _ba, _bv);
        emit TokenReceived(tokenAddress, _ba, _bv);
        emit TokensSent(tokenAddress, msg.sender, _av + _bv);
        return true;
    }

    function sendERC20(address[] memory _receiver, uint256[] memory _amount)
        public
        nonReentrant
        returns (bool)
    {
        uint256 totalSend = 0;
        IERC20 token = IERC20(tokenAddress);
        require(_receiver.length <= 100, "receiver list is overload!");
        require(
            _receiver.length == _amount.length,
            "lacking of amount infomation, please check again!"
        );
        for (uint256 j = 0; j < _receiver.length; j++) {
            token.transferFrom(msg.sender, _receiver[j], _amount[j]);
            emit TokenReceived(tokenAddress, _receiver[j], _amount[j]);
            totalSend += _amount[j];
        }
        emit TokensSent(tokenAddress, msg.sender, totalSend);
        return true;
    }

    function sendCoin(address[] memory _receiver, uint256[] memory _amount)
        public
        payable
        nonReentrant
        returns (bool)
    {
        require(_receiver.length <= 100, "receiver list is overload!");
        require(
            _receiver.length == _amount.length,
            "lacking of amount infomation, please check again!"
        );

        uint256 total = msg.value;

        for (uint256 i = 0; i < _receiver.length; i++) {
            require(total >= _amount[i]);
            (bool success, ) = payable(_receiver[i]).call{value: _amount[i]}(
                ""
            );
            require(success, "Transfer failed.");
            emit ETHReceived(_receiver[i], _amount[i]);
            total = total.sub(_amount[i]);
        }
        emit ETHSent(msg.sender, msg.value);
        return true;
    }

    function setTokenAddress(address _tokenAddress)
        external
        onlyOwner
        returns (bool)
    {
        tokenAddress = _tokenAddress;
        emit TokenAddressChanged(_tokenAddress);
        return true;
    }
}

在开始时的混音中,我批准合约地址支付 x 数量的代币,之后我调用

sendERC20
发送多笔付款的功能以及我所做的一切。

但是当我想在反应中使用它时,它在元掩码和事务失败中向我显示此错误,我想知道问题是什么?

import React, { useState, useEffect } from 'react';
import Web3 from 'web3';

function MultiSendToken() {
  const [web3, setWeb3] = useState(null);
  const [account, setAccount] = useState('');
  const [multiSendContractAddress, setMultiSendContractAddress] = useState('0xf5ba214d32Ac6f9F27e970207da342D299f325d7');
  const [tokenAddress, setTokenAddress] = useState('0x3b7513042790a6e07729b40138cCB46547FB4e3A'); // Token contract address
  const [addressA, setAddressA] = useState('0x8EC1E147971A9f4dA725CCc031E8F1c85c4E8F6a');
  const [addressB, setAddressB] = useState('0x8EC1E147971A9f4dA725CCc031E8F1c85c4E8F6a');
  const [amountA, setAmountA] = useState('1');
  const [amountB, setAmountB] = useState('1');

  useEffect(() => {
    if (window.ethereum) {
      const web3Instance = new Web3(window.ethereum);
      setWeb3(web3Instance);
      window.ethereum.request({ method: 'eth_requestAccounts' })
        .then(accounts => {
          setAccount(accounts[0]);
        })
        .catch(err => {
          console.error('User denied account access or error occurred:', err);
        });
    } else {
      alert('Please install MetaMask!');
    }
  }, []);

  const approveTokens = async () => {
    const totalAmount = (parseFloat(amountA) + parseFloat(amountB)).toString();
    const tokenABI = [{
      "constant": false,
      "inputs": [{ "name": "_spender", "type": "address" }, { "name": "_value", "type": "uint256" }],
      "name": "approve",
      "outputs": [{ "name": "", "type": "bool" }],
      "type": "function"
    }];
    const tokenContract = new web3.eth.Contract(tokenABI, tokenAddress);
    const totalAmountInWei = web3.utils.toWei(totalAmount, 'mwei'); // Convert total amount to wei with 6 decimals

    try {
      await tokenContract.methods.approve(multiSendContractAddress, totalAmountInWei).call({ from: account });
      console.log('Approval successful for total amount:', totalAmountInWei);
      sendToken(); // Proceed to send tokens after approval
    } catch (error) {
      console.error('Approval failed:', error);
      alert('Approval failed. Check console for more details.');
    }
  };

  const sendToken = async () => {
    const multiSendABI = [
      {
        "inputs": [
          { "name": "_aa", "type": "address" },
          { "name": "_ba", "type": "address" },
          { "name": "_av", "type": "uint256" },
          { "name": "_bv", "type": "uint256" }
        ],
        "name": "sendToken",
        "outputs": [{ "name": "", "type": "bool" }],
        "type": "function",
        "stateMutability": "nonpayable"
      }
    ];
    const contract = new web3.eth.Contract(multiSendABI, multiSendContractAddress);
    const avInWei = web3.utils.toWei(amountA, 'mwei'); // Converting to smallest unit based on 6 decimals
    const bvInWei = web3.utils.toWei(amountB, 'mwei');

    try {
      const response = await contract.methods.sendToken(addressA, addressB, avInWei, bvInWei).send({ from: account });
      console.log('Transaction Successful:', response);
      alert('Tokens sent successfully!');
    } catch (error) {
      console.error('Failed to send tokens:', error);
      alert('Transaction failed! See console for details.');
    }
  };

  return (
    <div>
      <h2>MultiSend Token Transfer</h2>
      <input type="text" value={tokenAddress} onChange={e => setTokenAddress(e.target.value)} placeholder="Token Contract Address" />
      <input type="text" value={multiSendContractAddress} onChange={e => setMultiSendContractAddress(e.target.value)} placeholder="MultiSend Contract Address" />
      <input type="text" value={addressA} onChange={e => setAddressA(e.target.value)} placeholder="Address A" />
      <input type="text" value={addressB} onChange={e => setAddressB(e.target.value)} placeholder="Address B" />
      <input type="text" value={amountA} onChange={e => setAmountA(e.target.value)} placeholder="Amount for Address A" />
      <input type="text" value={amountB} onChange={e => setAmountB(e.target.value)} placeholder="Amount for Address B" />
      <button onClick={approveTokens}>Approve and Send Tokens</button>
    </div>
  );
}

错误信息:

export default MultiSendToken;
Failed to send tokens: TransactionRevertedWithoutReasonError: Transaction has been reverted by the EVM:
 {"blockHash":"0xa4fccf0ecacf834f634b090ce0c6dbb1d6e14f18f3a61d3d7057984bdb185913","blockNumber":"6238953","cumulativeGasUsed":"219787","effectiveGasPrice":"2500000015","from":"0x53a1d6bab5d93e93b7be978f109967c581e4b683","gasUsed":"37505","logs":[{"address":"0x0000000000000000000000000000000000001010","topics":["0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63","0x0000000000000000000000000000000000000000000000000000000000001010","0x00000000000000000000000053a1d6bab5d93e93b7be978f109967c581e4b683","0x00000000000000000000000009207a6efee346cb3e4a54ac18523e3715d38b3f"],"data":"0x00000000000000000000000000000000000000000000000000005546c881790000000000000000000000000000000000000000000000000006e84ce7162498310000000000000000000000000000000000000000000000c66c71f3e72ecad40900000000000000000000000000000000000000000000000006e7f7a04da31f310000000000000000000000000000000000000000000000c66c72492df74c4d09","blockNumber":"6238953","transactionHash":"0xe3fcda0fb3706298a2f5c43356f9076887b2f368a34d938ebdeaf2dca9a9abd9","transactionIndex":"2","blockHash":"0xa4fccf0ecacf834f634b090ce0c6dbb1d6e14f18f3a61d3d7057984bdb185913","logIndex":"6","removed":false}],"logsBloom":"0x00000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000008000000000000000010000000000000000000000000000000000000000800000000000000000000100000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000004000000004000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004000000000000000000001000000400000000000000000000000100000000000000000000000000000000000010000000000000000000000000000000000100000","status":"0","to":"0xf5ba214d32ac6f9f27e970207da342d299f325d7","transactionHash":"0xe3fcda0fb3706298a2f5c43356f9076887b2f368a34d938ebdeaf2dca9a9abd9","transactionIndex":"2","type":"2","events":{}}

ethereum solidity smartcontracts web3js metamask
1个回答
0
投票

我之前也遇到过同样的错误,并询问过在以太坊上。来自答案:

可能发生的情况是 Metamask 对 具有相同参数的合约,以模拟如果 交易发生了。如果它注意到静态调用 恢复,它会给你这个错误 - 因为很可能是真正的 交易也会恢复。

sendToken
函数的参数之一类型错误。记录所有参数以查看它们的值。

© www.soinside.com 2019 - 2024. All rights reserved.