Uniswap 方法 getAmountsOut() returns 使用 Hardhat 主网分叉时的错误值

Uniswap method getAmountsOut() returns wrong value when using Hardhat mainnet fork

在我的安全帽测试中,我使用 Uniswap 的 getAmountsOut 来获取以美元为单位的 ETH 价格(使用 DAI)。目前 returns 2766 美元作为 ETH 的价格是正确的。这是我成功获取价格的测试:

require('dotenv').config()
const { ethers } = require("hardhat");

const UNISWAPV2_ROUTER02_ADDRESS = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D";
const UNISWAPV2_ROUTER02_ABI = [{ "inputs": [{ "internalType": "uint256", "name": "amountIn", "type": "uint256" }, { "internalType": "address[]", "name": "path", "type": "address[]" }], "name": "getAmountsOut", "outputs": [{ "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" }], "stateMutability": "view", "type": "function" }]

const DAI_ADDRESS = "0x6b175474e89094c44da98b954eedeac495271d0f";
const WETH_ADDRESS = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";

describe("eth-price-test", function () {
    it("Test fetch Eth price", async function () {
        const provider = new ethers.providers.WebSocketProvider(process.env.INFURA_WEB_SOCKET)
        const wallet = new ethers.Wallet(process.env.ETH_PRIVATE_KEY, provider)
        const signer = wallet.provider.getSigner(wallet.address)
        let uniswap = new ethers.Contract(
            UNISWAPV2_ROUTER02_ADDRESS,
            UNISWAPV2_ROUTER02_ABI,
            signer,
        );

        const amountEth = await uniswap.getAmountsOut(
            1,
            [WETH_ADDRESS, DAI_ADDRESS]
        )

        console.log(`1 Eth = ${amountEth[1].toString()} USD`)
    });
});

然而,当我使用连接到 Hardhat 主网分叉的签名者时,返回的价格是 3993 美元,这要高得多。我得到这样的签名者:

signer = ethers.provider.getSigner(process.env.ETH_PUBLIC_KEY)
let uniswap = new ethers.Contract(
  UNISWAPV2_ROUTER02_ADDRESS,
  UNISWAPV2_ROUTER02_ABI,
  signer,
);

这里是我的hardhat.config.js的相关部分供参考:

module.exports = {
  solidity: "0.5.0",
  networks: {
    hardhat: {
      forking: {
        url: process.env.ALCHEMY_URL
      }
    }
  }
};

知道为什么会有这么大的价格差异吗?即使我将主网分叉挂到不同的区块,它总是 returns $3993...

提前致谢!

我找到了修复方法!通过在部署 Uniswap 合约时使用 ethers.provider 而不是 signergetAmountsOut() 将使用挂钩区块正确获取 Eth 的价格。

let uniswap = new ethers.Contract(
  UNISWAPV2_ROUTER02_ADDRESS,
  UNISWAPV2_ROUTER02_ABI,
  ethers.provider // using provider instead of signer here
);