Невозможность декодирования данных транзакции
Я пытаюсь декодировать данные из транзакции в тесте смарт-контракта, используя инструкции из документации 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);
});
});
2 ответа
uint
это псевдоним для. Сигнатура функции всегда генерируется из выражения, содержащего длину байта (в вашем случае
uint256
).
Итак, вам нужно пройти
addLiquidityETH(address,uint256,uint256,uint256,address,uint256)
вместо
addLiquidityETH
к
decodeFunctionData()
функция.
Нашел решение:
Я импортировал свой исходный контракт, думая, что интерфейс, который мне нужен в моем тесте, был интерфейсом моего контракта:
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);
});
});