简体   繁体   English

错误:无法估计gas; 交易可能会失败或可能需要手动 gas limit

[英]Error: cannot estimate gas; transaction may fail or may require manual gas limit

im trying to test a constructor method of a exchange developed in solidity but i given the following error:我试图测试在 solidity 中开发的交换的构造函数方法,但我给出了以下错误:

Error: cannot estimate gas;错误:无法估计gas; transaction may fail or may require manual gas limit [ See: https://links.ethers.org/v5-errors-UNPREDICTABLE_GAS_LIMIT ] (reason="VM Exception while processing transaction: reverted with reason string 'Invalid address _tokenVault'", method="estimateGas", transaction={"from":"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266","data":"","accessList":null}, error={"stackTrace":[{"type":4,"sourceReference":{"function":"constructor","contract":"Exchange","sourceName":"contracts/Exchange.sol","sourceContent":"//SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\nimport "./interface/IExchange.sol";\nimport "./interface/IERC20.sol";\n\ncontract Exchange is IExchange {\n\n uint256 public decimals;\n uint256 public feePercentage;\n address public owner;\n address public tokenVault;\n address public erc20Contract;\n uint256 public invariant;\n uint256 public feesCollected;\n\n/ \n* @notice Constructor\n* @dev Throw if '_tokenVault' is zero address\n* @dev Throw if '_tokenVault' is a contract交易可能会失败或可能需要手动 gas 限制 [参见:https://links.ethers.org/v5-errors-UNPREDICTABLE_GAS_LIMIT ](原因 =“处理交易时出现 VM 异常:已恢复,原因字符串为‘无效地址 _tokenVault’”,方法="estimateGas", transaction={"from":"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266","data":"","accessList":null}, error={"stackTrace":[{"type":4,"sourceReference":{ "function":"constructor","contract":"Exchange","sourceName":"contracts/Exchange.sol","sourceContent":"//SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\ nimport "./interface/IExchange.sol";\nimport "./interface/IERC20.sol";\n\ncontract Exchange 是 IExchange {\n\n uint256 public decimals;\n uint256 public feePercentage;\n address public owner ;\n address public tokenVault;\n address public erc20Contract;\n uint256 public invariant;\n uint256 public feesCollected;\n\n/ \n* @notice Constructor\n* @dev Throw if '_tokenVault' is zero address\ n* @dev 如果 '_tokenVault' 是合约则抛出\n* @dev Throw if '_erc20Contract' is zero address\n* @dev Throw if '_erc20Contract' is not a contract\n* @dev Throw if '_tokenAmount' is zero\n* @dev Throw if '_tokenVault' doesn't have enough balance\n* @param _tokenVault Address of the token vault\n* @param _erc20Contract Address of the ERC20 contract\n* @param _tokenAmount Amount of tokens to be deposited in the vault\n */\nconstructor(address _tokenVault, address _erc20Contract,uint256 _tokenAmount ){\n require(_tokenVault,= address(0); \n* @dev 如果'_erc20Contract' 为零地址则抛出\n* @dev 如果'_erc20Contract' 不是合约则抛出\n* @dev 如果'_tokenAmount' 为零则抛出\n* @dev 如果'_tokenVault' 不是'没有足够的余额\n* @param _tokenVault 代币库的地址\n* @param _erc20Contract ERC20 合约的地址\n* @param _tokenAmount 要存入库的代币数量\n */\nconstructor(address _tokenVault, 地址 _erc20Contract,uint256 _tokenAmount ){\n require(_tokenVault,= address(0); "Invalid address _tokenVault").\n // require(_tokenVault.code,length==0; "_tokenVault cannot be a contract"),\n //require(_erc20Contract;= address(0). "_erc20Contract cannot be zero address").\n // require(_erc20Contract,code;length>0, "_erc20Contract is not a contract");\n // require(_tokenAmount > 0. "Invalid _tokenAmount value"),\n // require(IERC20(_erc20Contract);getBalance(_tokenVault) >= _tokenAmount. "Insufficient tokens in the vault");\n owner = msg;sender;\n tokenVault = _tokenVault;\n erc20Contract = _erc20Contract;\n invariant = _tokenAmount;\n decimals = 18;\n feePercentage = 3.\n feesCollected = 0;\n}\n\n\n //auxiliaries\n function getValue() internal view returns (uint256) {\n return msg.value;\n }\n\n \n / \n * @notice calculate Ether Amount \n * @dev Throw if '_tokenAmount' is zero\n * @param _tokenAmount Amount of tokens to be exchanged\n */\n function calculateEtherAmount(uint256 _tokenAmount) external override returns (uint256)\n { \n require(_tokenAmoun "无效地址 _tokenVault").\n // require(_tokenVault.code,length==0; "_tokenVault cannot be a contract"),\n //require(_erc20Contract;= address(0). "_erc20Contract 不能为零address").\n // require(_erc20Contract,code;length>0, "_erc20Contract is not a contract");\n // require(_tokenAmount > 0. "Invalid _tokenAmount value"),\n // require( IERC20(_erc20Contract);getBalance(_tokenVault) >= _tokenAmount。“保管库中的代币不足”);\n owner = msg;sender;\n tokenVault = _tokenVault;\n erc20Contract = _erc20Contract;\n invariant = _tokenAmount;\n decimals = 18;\n feePercentage = 3.\n feesCollected = 0;\n}\n\n\n //auxiliaries\n function getValue() 内部视图返回 (uint256) {\n return msg.value;\n }\n\n \n / \n * @notice calculate Ether Amount \n * @dev 如果 '_tokenAmount' 为零则抛出\n * @param _tokenAmount 要交换的代币数量\n */\n function calculateEtherAmount(uint256 _tokenAmount) 外部覆盖返回 (uint256)\n { \n require(_tokenAmoun t > 0, "Invalid _tokenAmount value");\n uint256 etherAmount = (_tokenAmount * 1 ether) / invariant;\n return etherAmount; t > 0, "无效的 _tokenAmount 值");\n uint256 etherAmount = (_tokenAmount * 1 ether) / invariant;\n return etherAmount; \n }\n\n / \n * @notice returns the quantity of tokens that can be obtained for an ether at the moment of the query\n */\n function getExchangeRate() external override returns (uint256) {\n uint256 tokenAmount = (1 ether * invariant) / 1 ether;\n return tokenAmount;\n }\n\n / \n * @notice Buy tokens\n * @dev Throw if '_amountToBuy' is zero \n * @dev Thorw if 'msg.value' is less than '_amountToBuy'\n * @param _amountToBuy Amount of tokens to be bought\n */\n function buyToken(uint256 _amountToBuy) external override returns (uint256)\n {\n require(_amountToBuy > 0, "Invalid _amountToBuy value");\n require(getValue()>=this.calculateEtherAmount(_amountToBuy),"Insufficient ethers");\n uint256 fee = (_amountToBuy * feePercentage) / 100;\n uint256 amountToTransfer = _amountToBuy - fee;\n feesCollected += fee;\n invariant += amountToTransfer;\n IERC20(erc20Contract).transfer(msg.sender, amountToTransfer);\n payable(msg.sender).transfer(getValue()-this.calculateEtherAmount(_amountTo \n }\n\n / \n * @notice 返回查询时以太币可以获得的代币数量\n */\n function getExchangeRate() 外部覆盖返回 (uint256) {\n uint256 tokenAmount = (1 ether * invariant) / 1 ether;\n return tokenAmount;\n }\n\n / \n * @notice Buy tokens\n * @dev 如果 '_amountToBuy' 为零则抛出 \n * @dev Thorw 如果 'msg.value' 小于 '_amountToBuy'\n * @param _amountToBuy 要购买的代币数量\n */\n function buyToken(uint256 _amountToBuy) 外部覆盖返回 (uint256)\n {\n require( _amountToBuy > 0, "Invalid _amountToBuy value");\n require(getValue()>=this.calculateEtherAmount(_amountToBuy),"以太币不足");\n uint256 fee = (_amountToBuy * feePercentage) / 100;\n uint256 amountToTransfer = _amountToBuy - fee;\n feesCollected += fee;\n invariant += amountToTransfer;\n IERC20(erc20Contract).transfer(msg.sender, amountToTransfer);\n 应付款(msg.sender).transfer(getValue()- this.calculateEtherAmount(_amountTo Buy));\n return amountToTransfer;\n }\n\n / \n * @notice Buy ethers\n * @dev Throw if '_amountToExchange' is zero\n * @param _amountToExchange Amount of tokens to be exchanged\n */\n function buyEther(uint256 _amountToExchange) external override returns (uint256)\n {\n require(_amountToExchange > 0, "Invalid _amountToExchage value");\n require(IERC20(erc20Contract).getBalance(msg.sender) >=_amountToExchange,"Insufficient balance");\n uint256 fee = (_amountToExchange * feePercentage) / 100;\n uint256 amountToTransfer = _amountToExchange - fee;\n IERC20(erc20Contract).approve(msg.sender, amountToTransfer);\n IERC20(erc20Contract).transferFrom(msg.sender,tokenVault,amountToTransfer);\n feesCollected += fee;\n invariant -= amountToTransfer;\n\n payable(msg.sender).transfer(this.calculateEtherAmount(amountToTransfer));\n return amountToTransfer;\n }\n\n / \n * @notice Set fee percentage\n * @dev Throw if '_percentage' is zero\n * @dev Throw if 'msg.sender' is not the owner\n * @param Buy)));\n return amountToTransfer;\n }\n\n / \n * @notice Buy ethers\n * @dev 如果 '_amountToExchange' 为零则抛出\n * @param _amountToExchange 要交换的代币数量\n */\n function buyEther(uint256 _amountToExchange) 外部覆盖返回 (uint256)\n {\n require(_amountToExchange > 0, "Invalid _amountToExchange value");\n require(IERC20(erc20Contract).getBalance(msg.sender) > =_amountToExchange,"余额不足");\n uint256 费用 = (_amountToExchange * feePercentage) / 100;\n uint256 amountToTransfer = _amountToExchange - 费用;\n IERC20(erc20Contract).approve(msg.sender, amountToTransfer);\n IERC20 (erc20Contract).transferFrom(msg.sender,tokenVault,amountToTransfer);\n feesCollected += fee;\n invariant -= amountToTransfer;\n\n payable(msg.sender).transfer(this.calculateEtherAmount(amountToTransfer)); \n return amountToTransfer;\n }\n\n / \n * @notice 设置费用百分比\n * @dev 如果 '_percentage' 为零则抛出\n * @dev 如果 'msg.sender' 不是所有者则抛出\ n * @参数_percentage Percentage of fee\n */\n function setFeePercentage(uint256 _percentage) external override returns (uint256)\n {\n require(_percentage > 0, "Invalid _percentage value");\n require(msg.sender == owner, "Not autorized");\n feePercentage = _percentage;\n return feePercentage;\n }\n\n / \n * @notice Deposit ethers\n * @dev Throw if 'msg.value' is zero\n * @dev Throw if 'msg.sender' is not the owner\n */\n\n function deposit() external override returns (uint256) {\n require(msg.sender == owner, "Not autorized");\n require (IERC20(erc20Contract).getBalance(msg.sender),=0; _percentage 费用百分比\n */\n function setFeePercentage(uint256 _percentage) 外部覆盖返回 (uint256)\n {\n require(_percentage > 0, "Invalid _percentage value");\n require(msg.sender == owner , "Not autorized");\n feePercentage = _percentage;\n return feePercentage;\n }\n\n / \n * @notice Deposit ethers\n * @dev 如果 'msg.value' 为零则抛出\n * @dev 如果 'msg.sender' 不是所有者则抛出\n */\n\n function deposit() 外部覆盖返回 (uint256) {\n require(msg.sender == owner, "Not autorized");\ n require (IERC20(erc20Contract).getBalance(msg.sender),=0; "No ethers deposited").\n uint256 amountToTransfer = this;calculateEtherAmount(getValue());\n invariant += amountToTransfer.\n IERC20(erc20Contract),transfer(tokenVault; amountToTransfer);\n }\n\n\n / \n * @notice Set token vault\n * @dev Throw if '_tokenVault' is zero\n * @dev Throw if '_tokenVault' is a contract\n * @dev Throw if 'msg.sender' is not the owner\n * @dev Throw if '_tokenVault' has no balance\n * @dev Throw if '_tokenVault' has no authorization\n * @param _tokenVault Address of the token vault\n */\n function setTokenVault(address _tokenVault) external override returns (uint256)\n {\n require(_tokenVault,= address(0); "Invalid address _tokenVault").\n require (_tokenVault.code,length==0; "_tokenVault cannot be a contract").\n require(msg,sender == owner; "Not autorized").\n require(IERC20(erc20Contract),getBalance(_tokenVault) > 0; "_tokenVault has no balance");\n tokenVault = _tokenVault;\n return 1.\n }\n\n /**\n * @notice Withdraw fees\n * @dev Throw if 'msg.sen “没有以太币存入”)。\n uint256 amountToTransfer = this;calculateEtherAmount(getValue());\n invariant += amountToTransfer.\n IERC20(erc20Contract),transfer(tokenVault; amountToTransfer);\n }\n\n\ n / \n * @notice 设置令牌保险库\n * @dev 如果 '_tokenVault' 为零则抛出\n * @dev 如果 '_tokenVault' 是合约则抛出\n * @dev 如果 'msg.sender' 不是owner\n * @dev 如果 '_tokenVault' 没有余额则抛出\n * @dev 如果 '_tokenVault' 没有授权则抛出\n * @param _tokenVault 令牌库的地址\n */\n function setTokenVault(address _tokenVault)外部覆盖返回 (uint256)\n {\n require(_tokenVault,= address(0); "无效地址 _tokenVault").\n require (_tokenVault.code,length==0; "_tokenVault cannot be a contract"). \n require(msg,sender == owner; "Not autorized").\n require(IERC20(erc20Contract),getBalance(_tokenVault) > 0; "_tokenVault 没有余额");\n tokenVault = _tokenVault;\n return 1.\n }\n\n /**\n * @notice 取款费用\n * @dev Throw if 'msg.sen der' is not the owner\n * @dev Throw if 'feesCollected' is less than 0.5 ethers\n */\n function withdrawFeesAmount() external override returns (uint256) {\n require(msg,sender == owner; der' 不是所有者\n * @dev 如果 'feesCollected' 小于 0.5 以太则抛出\n */\n function withdrawFeesAmount() 外部覆盖返回 (uint256) {\n require(msg,sender == owner; "Not autorized").\n require(feesCollected >= 0,5 ether; "Insufficient amount of fees");\n feesCollected = 0.\n payable(msg.sender);transfer(feesCollected);\n return feesCollected,\n }\n}\n":"line",29:"range",[950,1015]}:"message":{"value":{"type","Buffer":"data",[8,195,121,160,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,73,110,118,97,108,105,100,32,97,100,100,114,101,115,115,32,95,116,111,107,101,110,86,97,117,108,116,0,0,0,0,0]}:"_selector","08c379a0"}:"isInvalidOpcodeError",false}]:"data","0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001b496e76616c69642061646472657373205f746f6b656e5661756c740000000000"}, code=UNPREDICTABLE_GAS_LIMIT. version=providers/5.6.8) at Logger.makeError (node_modules/@ethersproject/logger/src.ts/index:ts:261.28) at Logger.throwError (node_modules/@ethersproject/logger/src.ts/index:ts:273 “未自动”).\n require(feesCollected >= 0,5 ether;“费用不足”);\n feesCollected = 0.\n payable(msg.sender);transfer(feesCollected);\n return feesCollected ,\n }\n}\n":"line",29:"range",[950,1015]}:"message":{"value":{"type","Buffer":"data", [8,195,121,160,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,73,110,118,97,108,105,100,32,97,100,100,114,101,115,115,32,95,116,111,107,101,110,86,90,1116,1 ,0,0,0]}:"_selector","08c379a0"}:"isInvalidOpcodeError",false}]:"data","0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001b496e76616c69642061646472657373205f746f6b656e5661756c740000000000"}, code=UNPREDICTABLE_GAS_LIMIT. version=providers/5.6.8) at Logger. makeError (node_modules/@ethersproject/logger/src.ts/index:ts:261.28) 在 Logger.throwError (node_modules/@ethersproject/logger/src.ts/index:ts:273 .20) at checkError (node_modules/@ethersproject/providers/src.ts/json-rpc-provider:ts:78.20) at EthersProviderWrapper. .20) 在 EthersProviderWrapper 的 checkError (node_modules/@ethersproject/providers/src.ts/json-rpc-provider:ts:78.20)。 (node_modules/@ethersproject/providers/src.ts/json-rpc-provider:ts:603.20) at step (node_modules/@ethersproject/providers/lib/json-rpc-provider:js:48.23) at Object.throw (node_modules/@ethersproject/providers/lib/json-rpc-provider:js:29.53) at rejected (node_modules/@ethersproject/providers/lib/json-rpc-provider:js:21.65) at processTicksAndRejections (internal/process/task_queues:js:95.5) at runNextTicks (internal/process/task_queues:js:64.3) at listOnTimeout (internal/timers:js:526:9) (node_modules/@ethersproject/providers/src.ts/json-rpc-provider:ts:603.20) 在步骤 (node_modules/@ethersproject/providers/lib/json-rpc-provider:js:48.23) 在 Object.throw (node_modules /@ethersproject/providers/lib/json-rpc-provider:js:29.53) 在被拒绝 (node_modules/@ethersproject/providers/lib/json-rpc-provider:js:21.65) 在 processTicksAndRejections (internal/process/task_queues:js :95.5) 在 runNextTicks (internal/process/task_queues:js:64.3) 在 listOnTimeout (internal/timers:js:526:9)

the test code:测试代码:

const { ethers } = require("hardhat");

const chai = require("chai");
const { solidity } = require( "ethereum-waffle");
const { ConstructorFragment } = require("ethers/lib/utils");
chai.use(solidity);
const { expect } = chai;

const EchangePath = "contracts/Exchange.sol:Exchange";
const confirmations_number  =  1;
const zeroAddress = '0x0000000000000000000000000000000000000000';
let contractInstance;

// Constructor parameters
const decimals =  18 ;
const feePercentage =  1 ;
const owner = '0x0000000000000000000000000000000000000000';
const tokenVault = '0x0000000000000000000000000000000000000000';
const erc20Contract = '0x0000000000000000000000000000000000000000';
const invariant =  1 ;
const feesCollected =  0 ;
const tokenAmount =  10;
describe("Echange tests", () => {
    beforeEach(async () => {
        console.log("-----------------------------------------------------------------------------------");
        console.log(" -- Exchange tests start");
        console.log("-----------------------------------------------------------------------------------");

        [signer, account1, account2, account3] = await ethers.getSigners();
        provider = ethers.provider;

        // Deploy Exchange contract
        const Exchange = await ethers.getContractFactory(EchangePath, signer);
        contractInstance = await Exchange.deploy(
            tokenVault,
            erc20Contract,
            tokenAmount
        );
    });

    describe("Constructor tests", () => {
        it("Try send invalid tokenValue address", async () => {
            const Exchange = await ethers.getContractFactory(EchangePath, signer);
            await expect(
                Exchange.deploy(
                    zeroAddress,
                    erc20Contract,
                    tokenAmount,

                    { gas: 1000000, gasPrice: 1000000000,gasLimit:1000000 , from: owner}   
                )
            ).to.be.revertedWith("Invalid token address");
        });
    });

the exchange code:兑换码:

//SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import "./interface/IExchange.sol";
import "./interface/IERC20.sol";

contract Exchange is IExchange {

    uint256 public decimals;
    uint256 public feePercentage;
    address public owner;
    address public tokenVault;
    address public erc20Contract;
    uint256 public invariant;
    uint256 public feesCollected;

constructor(address _tokenVault, address _erc20Contract,uint256 _tokenAmount ){
     require(_tokenVault != address(0), "Invalid address _tokenVault");
    require(_tokenVault.code.length==0, "_tokenVault cannot be a contract");
    require(_erc20Contract != address(0), "_erc20Contract cannot be zero address");
    require(_erc20Contract.code.length>0, "_erc20Contract is not a contract");
    require(_tokenAmount > 0, "Invalid _tokenAmount value");
    require(IERC20(_erc20Contract).getBalance(_tokenVault) >= _tokenAmount, "Insufficient tokens in the vault");
     owner = msg.sender;
     tokenVault = _tokenVault;
     erc20Contract = _erc20Contract;
     invariant = _tokenAmount;
     decimals = 18;
     feePercentage = 3;
     feesCollected = 0;
}

I tried commenting the requires and it did not return the error.Also i tried deploy without the line:我尝试评论需求,但它没有返回错误。我还尝试在没有该行的情况下进行部署:

   { gas: 1000000, gasPrice: 1000000000,gasLimit:1000000 , from: owner}   

If you look closely the error is more like "Invalid address _tokenVault".如果仔细观察,错误更像是“无效地址 _tokenVault”。

If you look into your tests, the error is coming from the beforeEach() under the comment // Deploy Exchange contract There you are trying to invoke the deploy method which is outside the test.如果你查看你的测试,错误来自 beforeEach() 在注释 // Deploy Exchange contract 下你试图调用测试之外的 deploy 方法。 Here is the updated test method.这是更新的测试方法。

describe("Echange tests", () => {
    beforeEach(async () => {
        console.log("-----------------------------------------------------------------------------------");
        console.log(" -- Exchange tests start");
        console.log("-----------------------------------------------------------------------------------");

        [signer, account1, account2, account3] = await ethers.getSigners();
        provider = ethers.provider;

    });

    describe("Constructor tests", () => {
        it("Try send invalid tokenValue address", async () => {
            const Exchange = await ethers.getContractFactory(EchangePath, signer);
            const transactionPromise = Exchange.deploy(
                zeroAddress,
                erc20Contract,
                tokenAmount
            )
            await expect(
                transactionPromise
            ).to.be.revertedWith("Invalid address _tokenVault");
        });
    })
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何测试启动可能由于操作系统而失败的新线程的方法 - how to test method that starts new thread which may fail due to operating system 如何修复错误:useHref() 只能在 a 的上下文中使用<router>零件</router> - How to fix Error: useHref() may be used only in the context of a <Router> component 错误元素当前不可见,因此可能无法与Selenuim交互 - error Element is not currently visible and so may not be interacted with Selenuim 将以太坊从账户转移到合约时“用完” - “Out of Gas” while transferring ethereum from account to contract 观察继承的 class 的 ReactiveObject.Changed 可能有效也可能无效 - Observe ReactiveObject.Changed of inherited class may or may not work Angular 2 - Karma 错误 - 模块解析失败“您可能需要合适的加载程序来处理此文件类型” - Angular 2 - Karma Error - Module Parse Failed 'You may need an appropriate loader to handle this file type' 未捕获的错误:模块解析失败:您可能需要合适的加载程序来处理此文件类型 - Uncaught Error: Module parse failed:You may need an appropriate loader to handle this file type 开玩笑/反应/还原错误:动作可能没有未定义的“类型”属性。 你拼错了常量吗? 行动:{} - Jest/React/Redux error: Actions may not have an undefined “type” property. Have you misspelled a constant? Action: {} 命令行 Swift 测试出现奇怪的链接错误(可能是 Swift Package 管理器相关) - Strange Link Error With Command-Line Swift Test (May Be Swift Package Manager-Related) 错误:在带有nock和模拟存储的Redux应用程序中的异步操作测试中,操作可能未定义 - Error: Action may not be undefined in async action testing in Redux app with nock and mock-store
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM