NomicFoundation / hardhat

Hardhat is a development environment to compile, deploy, test, and debug your Ethereum software.
https://hardhat.org
Other
7.19k stars 1.38k forks source link

ErrorInferrer: misleading "unexpected amount of data" message when a function has a fallback #1498

Open fvictorio opened 3 years ago

fvictorio commented 3 years ago

Given this contracts:

pragma solidity ^0.8.0;

import "hardhat/console.sol";

contract Foo {
  uint public x;
}

contract Bar {
  uint public y;

  fallback() external {}
}

contract CallFoo {
  function test(Foo foo) public {
    uint value = foo.x();
    console.logUint(value);
  }
}

and this script:

async function main() {
  const Foo = await hre.ethers.getContractFactory("Foo");
  const foo = await Foo.deploy();
  const Bar = await hre.ethers.getContractFactory("Bar");
  const bar = await Bar.deploy();

  const CallFoo = await hre.ethers.getContractFactory("CallFoo");
  const callFoo = await CallFoo.deploy();

  await callFoo.deployed();

  await callFoo.test(bar.address);
}

main()
  .then(() => process.exit(0))
  .catch(error => {
    console.error(error);
    process.exit(1);
  });

The error returned by hardhat is:

Error: Transaction reverted: function returned an unexpected amount of data

The error here is that CallFoo received the address of a Bar contract, not a Foo contract. But since it has a fallback function, the error isn't function selector was not recognized and there's no fallback function as it would be otherwise. This seems like something we could detect and give a better error message.

PaulRBerg commented 3 years ago

The exact same error happens when I interact with a contract "deployed" via the hardat_setCode JSON-RPC method.

I am deploying a mock USDC contract like this:


export async function deployUsdc(deployer: Signer): Promise<GodModeErc20> {
  const godModeErc20Artifact: Artifact = await artifacts.readArtifact("GodModeErc20");

  // Deploy via CREATE first, to get a runtime bytecode with the constructor arguments.
  const godModeErc20: GodModeErc20 = <GodModeErc20>(
    await waffle.deployContract(deployer, godModeErc20Artifact, [USDC_NAME, USDC_SYMBOL, USDC_DECIMALS])
  );

  // Get the runtime bytecode.
  const runtimeBytecode: string = await ethers.provider.getCode(godModeErc20.address);

  // Deploy the USDC contract at address(1).
  await ethers.provider.send("hardhat_setCode", [USDC_ADDRESS, runtimeBytecode]);

  // Load the USDC contract at address(1);
  const usdc: GodModeErc20 = GodModeErc20__factory.connect(USDC_ADDRESS, deployer);

  return usdc;
}

Then, I am passing USDC_ADDRESS as a function argument (see asset below) to a contract compiled and deployed normally (with the CREATE opcode).

function setFeed(IErc20 asset, IAggregatorV3 feed) external override onlyOwner {
    string memory symbol = asset.symbol();
    // ...
}

When I call setFeed, the tests fail with this error:

Error: Transaction reverted: function returned an unexpected amount of data
at ChainlinkOperator.setFeed (contracts/ChainlinkOperator.sol:99)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at runNextTicks (node:internal/process/task_queues:65:3)
at listOnTimeout (node:internal/timers:526:9)
at processTimers (node:internal/timers:500:7)
at async EthModule._estimateGasAction (/Users/paulrberg/workspace/hifi/monorepo/node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:425:7)
at async HardhatNetworkProvider.request (/Users/paulrberg/workspace/hifi/monorepo/node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:108:18)
at async EthersProviderWrapper.send (/Users/paulrberg/workspace/hifi/monorepo/node_modules/@nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20)

This doesn't happen when I deploy USDC the normal way.

PaulRBerg commented 3 years ago

Whoops .. the issue was that USDC_ADDRESS was set to address(1). That is where the ecrecover precompiled contract is located at.

Please nevermind my report above.

amirgamil commented 2 years ago

Can confirm I see this error trying to pass an address in the constructor

EDIT: Nvm, just needed to use ethers to pass a correctly formatted address!

donghwan2019 commented 1 year ago

@amirgamil hi Please tell me what to do to resolve this issue.