当前位置: 代码迷 >> 综合 >> 解决“function call to a non-contract account“问题
  详细解决方案

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

热度:62   发布时间:2023-12-21 06:13:11.0

? ? 今天在运行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 pairfunction 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
  相关解决方案