Solidity

無法解碼 tx 的數據

  • June 22, 2021

我正在嘗試使用 Ethers.js 文件中的說明對智能合約測試中的交易數據進行解碼,但我一直認為第一個參數(片段)無效:

Ethers.js

interface.decodeFunctionData( fragment , data ) ⇒ Result

Returns the decoded values from transaction data for fragment (see Specifying Fragments) for the given data.

ABI:

const abi = require('../artifacts/contracts/CoinX.sol/CoinX.json').abi;

Interface:

let ICoinX = new ethers.utils.Interface(abi);

AddLiquidityETH function on UniswapV2Router02.sol:

function addLiquidityETH(
 address token,
 uint amountTokenDesired,
 uint amountTokenMin,
 uint amountETHMin,
 address to,
 uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);

Main snippet on my test:

const tx = await router.addLiquidityETH(coinX.address, supply, supply, supply, addr1, MaxUint256, {
     value: supply
   });   
   const { data } = tx;

   console.log("Decoded data: ", await ICoinX.decodeFunctionData("addLiquidityETH", data));

我試過:

  1. 函式名稱:"addLiquidityETH".
  2. 函式簽名:"addLiquidityETH(address,uint,uint,uint,address,uint)""addLiquidityETH(address,uint,uint,uint,address,uint) external payable returns (uint,uint,uint)"
  3. 兩個簽名的嘆息:"0x1a3042d8""0x251511cc"
  4. interface.decodeFunctionResult( fragment , data )

…但錯誤仍然出現。

Error:

Error: no matching function (argument="name", value="addLiquidityETH", code=INVALID_ARGUMENT, version=abi/5.3.1)

謝謝您的幫助!

Full test:

const { parseEther, formatEther } = ethers.utils;
const { MaxUint256 } = ethers.constants;

const abi = require('../artifacts/contracts/CoinX.sol/CoinX.json').abi;

const routerAddress = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D";
const factoryAddress = "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f";

describe("Uniswap", function() {
 let router, coinX, ICoinX, factory;
 const supply = parseEther('100');

 before(async () => {
   router = await ethers.getContractAt("IUniswapV2Router02", routerAddress);
   factory = await ethers.getContractAt("IUniswapV2Factory", factoryAddress);

   const CoinX = await ethers.getContractFactory('CoinX');
   coinX = await CoinX.deploy(supply);
   await coinX.deployed();

   ICoinX = new ethers.utils.Interface(abi);
 });

 it("should allow trades", async function() {
   const wethAddr = await router.WETH();
   const [addr1] = await ethers.provider.listAccounts();

   console.log("coins before: ", formatEther(await coinX.balanceOf(addr1)));

   await coinX.approve(routerAddress, MaxUint256);

   const tx = await router.addLiquidityETH(coinX.address, supply, supply, supply, addr1, MaxUint256, {
     value: supply
   });

   const { data } = tx;

   console.log("Decoded data: ", await ICoinX.decodeFunctionData("addLiquidityETH", data)); // --------> Problem

   console.log("coins after: ", formatEther(await coinX.balanceOf(addr1)));

   const pairAddress = await factory.getPair(coinX.address, wethAddr);  
   console.log(pairAddress);  

 });
});

找到了解決方案:

我正在導入IUniswapV2Router02我的原始契約,認為我在測試中需要的介面是我的契約介面:

pragma solidity ^0.8.0;

//routers interface
import '@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol';     
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import '@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol';


contract CoinX is ERC20 {
   constructor(uint256 initialSupply) ERC20("CoinX", "CNX") {
       _mint(msg.sender, initialSupply);
   }
}

…實際上我需要IUniswapV2Router02直接進入我的測試而不是我的契約界面。

一旦我這樣做了,decodeFunctionData只需使用addLiquidityETH.

Full test (fixed):

const { parseEther, formatEther } = ethers.utils;
const { MaxUint256 } = ethers.constants;

//router's ABI
const abiRouter = require('../artifacts/@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol/IUniswapV2Router02.json').abi;

const routerAddress = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D";
const factoryAddress = "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f";

describe("Uniswap", function() {
 let router, coinX, myIUniswapV2Router02, factory;
 const supply = parseEther('100');

 before(async () => {
   router = await ethers.getContractAt("IUniswapV2Router02", routerAddress);
   factory = await ethers.getContractAt("IUniswapV2Factory", factoryAddress);

   const CoinX = await ethers.getContractFactory('CoinX');
   coinX = await CoinX.deploy(supply);
   await coinX.deployed();

   //router's interface on my test
   myIUniswapV2Router02 = new ethers.utils.Interface(abiRouter);
 });

 it("should allow trades", async function() {
   const wethAddr = await router.WETH();
   const [addr1] = await ethers.provider.listAccounts();

   console.log("coins before: ", formatEther(await coinX.balanceOf(addr1)));

   await coinX.approve(routerAddress, MaxUint256);

   const tx = await router.addLiquidityETH(coinX.address, supply, supply, supply, addr1, MaxUint256, {
     value: supply
   });

   const { data } = tx;

   //works as expected
   console.log("Decoded data: ", await myIUniswapV2Router02.decodeFunctionData("addLiquidityETH", data)); 
   
   console.log("coins after: ", formatEther(await coinX.balanceOf(addr1)));

   const pairAddress = await factory.getPair(coinX.address, wethAddr);  
   console.log(pairAddress);  

 });
});

引用自:https://ethereum.stackexchange.com/questions/102264