解决“function call to a non-contract account“问题

Posted sanqima

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决“function call to a non-contract account“问题相关的知识,希望对你有一定的参考价值。

    今天在运行UniswapV2合约调用getReserves()函数时,报"function call to a non-contract account"错误,如图(1)所示:

图(1) getReserve()函数调用的合约找不到

    出现这种情况的原因是:函数调用的合约找不到,可能的原因有:

  • 合约没有部署;
  • 合约地址错误;
  • api-key缺少访问权限;
  • codeHash没有配置;
  • 调用的合约在主网,而被调用的合约在测试网,即两合约没有在同一个网络。

    本例中,是由于UniswapV2Router02.sol里的pairFor()函数其codeHash没有更新,导致合约找不到。
UniswapV2Router02.sol 根据 factory、token0、token1、codeHash来生成pair地址,而codeHash使用的mainnet网络,应该使用本地网络的codeHash。
可通过web3.utils.keccak256(UniswapV2Pair.bytecode)计算codeHash,例子如下:

const Web3 = require('web3')
//配对合约的json文件
const UniswapV2Pair = require('../../artifacts/contracts/UniswapV2Factory.sol/UniswapV2Pair.json')
//设置网段 localhost、Rinkeby、mainnet
const web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545"))

let initCodeHash = null
let data = UniswapV2Pair.bytecode
if (!data.startsWith('0x')) data = '0x' + data
console.info('INIT_CODE_HASH:', initCodeHash = web3.utils.keccak256(data))

    得到codehash如下:

INIT_CODE_HASH: 0x36da00333ba9396db7d539011cd1c469351d4c58d439e5e918c9a07228bf291c

    注意:这个codeHash是通过配对合约的bytecode进行keccak256()生成的。在添加流动性时,工厂合约会检测这个pair合约是否存在,若不存在,则调用createPair()创建pair合约。

    在FlashLoanOne.sol,或者UniswapV2Router02.sol的pairFor()函数里,修改codehash,然后重新编译、部署智能合约。
    //FlashLoanOne.sol

  // calculates the CREATE2 address for a pair without making any external calls
    // codehash要根据factory合约,进行修改
    function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) 
        (address token0, address token1) = sortTokens(tokenA, tokenB);
        pair = address(uint(keccak256(abi.encodePacked(
                hex'ff',
                factory,
                keccak256(abi.encodePacked(token0, token1)),
                hex'36da00333ba9396db7d539011cd1c469351d4c58d439e5e918c9a07228bf291c' //修改此处
            ))));
    

    // fetches and sorts the reserves for a pair
    function getReserves(address factory, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) 
        (address token0,) = sortTokens(tokenA, tokenB);
        (uint reserve0, uint reserve1,) = IUniswapV2Pair(pairFor(factory, tokenA, tokenB)).getReserves();
        (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
    
## 编译智能合约
npx hardhat compile

## 部署智能合约
npx hardhat run script/deploy_flashloan.js

以上是关于解决“function call to a non-contract account“问题的主要内容,如果未能解决你的问题,请参考以下文章

云原生景观:可观察性和分析解决了什么问题?如何解决的?

vs2008解决方案资源管理器不显示解决方案

什么是 沙盒解决方案

解决PowerShell乱码问题

如何解决解决方案中现有项目的c#CS0006错误

关于问题解决与事件解决的思考