Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When hardhat is executing a task, an error occurs when accessing the contract mapping to obtain the account balance #6072

Open
Wangxiujie2001 opened this issue Dec 23, 2024 · 2 comments
Assignees
Labels
status:needs-more-info There's not enough information to start working on this issue

Comments

@Wangxiujie2001
Copy link

node version:v20.18.1
npm version:10.8.2
os:ubuntu 22.04
hardhat version:2.22.17

Error description:
When hardhat executes the run javascript script to deploy contracts and crowdfund, it can obtain the crowdfunding amount of the account through the address. However, when the contract deployment module and the contract interaction module are separated into two tasks, the interaction module attaches the contract address of the contract deployment module, and an error occurs when obtaining the crowdfunding amount of the account through the address.

Error phenomenon:

An unexpected error occurred:

Error: could not decode result data (value="0x", info={ "method": "fundOfAccount", "signature": "fundOfAccount(address)" }, code=BAD_DATA, version=6.13.4)
    at makeError (/home/w/hardhat/web3_tutorial/node_modules/ethers/src.ts/utils/errors.ts:694:21)
    at assert (/home/w/hardhat/web3_tutorial/node_modules/ethers/src.ts/utils/errors.ts:715:25)
    at Interface.decodeFunctionResult (/home/w/hardhat/web3_tutorial/node_modules/ethers/src.ts/abi/interface.ts:916:15)
    at staticCallResult (/home/w/hardhat/web3_tutorial/node_modules/ethers/src.ts/contract/contract.ts:346:35)
    at staticCall (/home/w/hardhat/web3_tutorial/node_modules/ethers/src.ts/contract/contract.ts:303:24)
    at Proxy.fundOfAccount (/home/w/hardhat/web3_tutorial/node_modules/ethers/src.ts/contract/contract.ts:351:41)
    at SimpleTaskDefinition.action (/home/w/hardhat/web3_tutorial/tasks/interact-fundMe.js:48:27)
    at Environment._runTaskDefinition (/home/w/hardhat/web3_tutorial/node_modules/hardhat/src/internal/core/runtime-environment.ts:351:14)
    at Environment.run (/home/w/hardhat/web3_tutorial/node_modules/hardhat/src/internal/core/runtime-environment.ts:184:14)
    at main (/home/w/hardhat/web3_tutorial/node_modules/hardhat/src/internal/cli/cli.ts:324:7) {
  code: 'BAD_DATA',
  value: '0x',
  info: { method: 'fundOfAccount', signature: 'fundOfAccount(address)' },
  shortMessage: 'could not decode result data'
}
@github-project-automation github-project-automation bot moved this to Backlog in Hardhat Dec 23, 2024
@galargh galargh added status:needs-more-info There's not enough information to start working on this issue and removed status:triaging labels Dec 23, 2024
@galargh
Copy link
Member

galargh commented Dec 23, 2024

Thanks for the report! Could you share your deployment script and hardhat configuration for us to better understand the issue?

I see that your project is in the web3_tutorial. Were you following some tutorial when you encountered this issue? If so, could you share a link to it?

@Wangxiujie2001
Copy link
Author

Hello my friend. My deployment task script is as follows

// depoly contract javascript of hardhat task
// const { ethers } = require("hardhat");

const { task } = require("hardhat/config")

task("depoly-fundme","depoly fundme contract in sepolia testnetwork").setAction(async (args, hre) => {
    // hre.network.provider.send("hardhat_setNonce",[
    //     "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
    //     "0x21",
    // ])
    
    const factory = await ethers.getContractFactory("FundMe");
    console.log("contract factory is created");
    //合约的部署需要先将其发到一个区块链网络节点,此时尚未部署完成,还需要将部署结果广播给其他节点,且共识完毕出块,至此合约部署完毕
    const fundMe = await factory.deploy();//合约可能在此开始广播共识过程
    await fundMe.waitForDeployment();//等待合约部署出块(真正的部署完毕)
    console.log(`fundme contract is deployed.the contract address is ${fundMe.target}`);//fundMe.target合约的部署地址
    if (hre.network.config.chainId == 11155111 && process.env.ETHEREUM_API_KEY) {
        console.log(`Waiting for 5 confirmations.`)
        await fundMe.deploymentTransaction().wait(5);
        verifyContract(fundMe.target, "");
    } else {
        console.log(`Verify skipped.`);
    }
    
    
})

//在etherscan上验证合约
async function verifyContract(fundMeAddr,args) {
    await hre.run("verify:verify", {
        address: fundMeAddr,
        constructorArguments: [args]
      });
}

The problem of this issue appears in the following hardhat task script

// const { ethers } = require("hardhat");
const { task } = require("hardhat/config");

task("interact-fundme","interaction with contract in testnetwork.")
    .addParam("addr", "fundMe contract address")
    .setAction(async (args,hre) => {
        
        const contractFactory=await ethers.getContractFactory("FundMe");
        
        const fundMe=await contractFactory.attach(args.addr)
        console.log("contract factory was created,instance was created.")

        //1.获取2个账户,1个账户为合约的拥有者,另一个账户为合约筹建1wei
        const [account1, account2] = await ethers.getSigners();

        //2.账户1向合约捐1wei,检查合约余额是否为1wei
        console.log(`账户1,地址:${account1.address}向合约${fundMe.target}转账1wei`);

        // hre.network.provider.send("hardhat_setNonce",[
        //     args.addr,
        //     "0x0",
        // ])

        const tx = await fundMe.fund({ value: 1 })
        await tx.wait()
        console.log(tx)
        var balance = await getBalance(fundMe.target);
        console.log(`账户1转账完成,合约${fundMe.target}的余额为:${balance}`)
        //3.账户2向合约捐1wei,检查合约余额是否为2wei
        console.log(`账户2,地址:${account2.address}向合约${fundMe.target}转账1wei`);

        // hre.network.provider.send("hardhat_setNonce",[
        //     args.addr,
        //     "0x1",
        // ])

        const tx2 = await fundMe.connect(account2).fund({ value: 1 })
        await tx2.wait()
        console.log(tx2)
        
        balance = await getBalance(fundMe.target);
        
        
     

        console.log(`账户2转账完成,合约${fundMe.target}的余额为:${balance}`)
        //4.检查账户1对应的mappng是否为1
        const account1V = await fundMe.fundOfAccount(account1.address)
        
        console.log(`合约${fundMe.target}中,地址为${account1.address}的值为:${account1V}`)
        //5.检查账户2对应的mappng是否为1
        const account2V = await fundMe.fundOfAccount(account2.address)
        console.log(`合约${fundMe.target}中,地址为${account2.address}的值为:${account2V}`)
        //6.使用合约拥有者,对合约进行销毁,转出
        const destoryTx = await fundMe.connect(account1).selfDesturct();
        await destoryTx.wait()
        console.log(`合约已经销毁`)
    })



//获取合约余额
//参数1:合约地址
async function getBalance(contractAddr) {
    try {
        const balance = await ethers.provider.getBalance(contractAddr);
        // return ethers.utils.formatEther(balance); // 转换为 Ether 单位
        return balance;
    } catch (error) {
        console.error('获取余额失败:', error);
        return null;  // 处理错误并返回 null
    }


}

An error occurred when executing this code await fundMe.fundOfAccount(account1.address)
My solidity contract code is as follows

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol";

//众筹合约
contract FundMe {
    mapping(address => uint256) public  fundOfAccount;
    AggregatorV3Interface internal dataFeed;
    //众筹的目标值
    uint256 public   TARGET=100*(10**18); //以法币为计价单位,1ether ->10^8 wei ->USD  USD/ETH
    bool public isFundScuccess=false;
    uint256 private depolyTimeStamp;
    uint256 private lockTimeStamp;

    address public owner;
    address public ERC20Addr;//投资者兑换通证的合约地址
    //构造函数,设置目标值和汇率 
    constructor() {
        owner=msg.sender;
      
        lockTimeStamp=5 minutes;//从部署合约到锁定结束合约,共有2分钟的窗口期
        depolyTimeStamp=block.timestamp;
        dataFeed = AggregatorV3Interface(
            0x694AA1769357215DE4FAC081bf1f309aDC325306
        );

    }

    

    //该函数为众筹函数,支持用户进行捐款。
    function fund() external payable {
        require(block.timestamp<depolyTimeStamp+lockTimeStamp,"funding has ended");
        fundOfAccount[msg.sender] += msg.value;
    }

    //该函数允许用户在众筹时间过后,未达到目标募捐资金,让用户发起退款
    function refund() external returns(bool) {
        require(block.timestamp>=depolyTimeStamp+lockTimeStamp,"funding has processing.");
        require(convertToFDCoin(address(this).balance) <TARGET,"Thank you for your contribution, the total crowdfunding goal has been reached");
        require(fundOfAccount[msg.sender]!=0,"you don't have any fund.");
        bool succ=payable(msg.sender).send(fundOfAccount[msg.sender]);
        require(succ,"the transfer failed");
        fundOfAccount[msg.sender]=0;//重置众筹资金
        return succ;
    }

    //查询众筹资金总额
    function fundBalance() public view returns (uint256,uint256) {
        return (address(this).balance,convertToFDCoin(address(this).balance));
    }
    
    //部署众筹合约者,在窗口期结束后,提取筹集的资金
    function getAllfunded() external payable returns(bool){
        require(block.timestamp>=depolyTimeStamp+lockTimeStamp,"funding has processing.");
        require(convertToFDCoin(address(this).balance)>=TARGET,"You do not need to withdraw the crowdfunding amount because the goal has not been reached");
        require(owner==msg.sender,"only the owner can withdraw");
        bool succ=payable(msg.sender).send(address(this).balance);
        require(succ,"Failed to withdraw crowdfunding amount");
        isFundScuccess=true;
        return succ;
    }
     /**
     * Returns the latest answer.
     */
    function getChainlinkDataFeedLatestAnswer() public view returns (int) {
        // prettier-ignore
        (
            /* uint80 roundID */,
            int answer,
            /*uint startedAt*/,
            /*uint timeStamp*/,
            /*uint80 answeredInRound*/
        ) = dataFeed.latestRoundData();
        return answer;
    }
    
    //内部函数,支持用户传递的以太币(单位:wei)将其转换为构造函数的法定货币
    function convertToFDCoin(uint256 ethAmount) internal view  returns(uint256){  
        uint256 ethPrice=uint256(getChainlinkDataFeedLatestAnswer());     
        return ethAmount*ethPrice/(10**8);//1ether ->10^8 wei ->USD  ETH/USD
    }

    function selfDesturct() external {
        require(msg.sender==owner,"Only the owner can destroy the contract");
        selfdestruct(payable(owner));
    }

    function updateFund(address account,uint256 newVal) external{
        require(fundOfAccount[account]>newVal,"the fund is not enough");
        require(msg.sender==ERC20Addr,"Illegal erc20 contract, please be careful about the source of the contract");
        fundOfAccount[account]=newVal;
    }

    function setERC20ContractAddr(address newErc20Addr) external {
        require(msg.sender==owner,"Only the owner can update erc20 contract address");
        ERC20Addr=newErc20Addr;
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status:needs-more-info There's not enough information to start working on this issue
Projects
Status: Backlog
Development

No branches or pull requests

2 participants