Solidity
無法解碼 tx 的數據
我正在嘗試使用 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));
我試過:
- 函式名稱:
"addLiquidityETH"
.- 函式簽名:
"addLiquidityETH(address,uint,uint,uint,address,uint)"
和"addLiquidityETH(address,uint,uint,uint,address,uint) external payable returns (uint,uint,uint)"
- 兩個簽名的嘆息:
"0x1a3042d8"
和"0x251511cc"
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); }); });