Created a contract a basic one to deploy on the Mumbai BC.
The same one of uni swaps the basic one, just with different addresses. Since this is in Mumbai BC, so I created it with wmatic.
then after approving all the addresses, I get this error without any explanation or option to understand where it failed when i try to singleswap.
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.7.6; pragma abicoder v2; import "hardhat/console.sol"; import '@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol'; import '@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol'; contract SwapExamples { // For the scope of these swap examples, // we will detail the design considerations when using // `exactInput`, `exactInputSingle`, `exactOutput`, and `exactOutputSingle`. // It should be noted that for the sake of these examples, we purposefully pass in the swap router instead of inherit the swap router for simplicity. // More advanced example contracts will detail how to inherit the swap router safely. ISwapRouter public immutable swapRouter; address public constant WMATIC = 0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889; address public constant WETH = 0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa; // For this example, we will set the pool fee to 0.3%. uint24 public constant poolFee = 3000; constructor(ISwapRouter _swapRouter) { swapRouter = _swapRouter; } /// @notice swapExactInputSingle swaps a fixed amount of WMATIC for a maximum possible amount of WETH /// using the WMATIC/WETH 0.3% pool by calling `exactInputSingle` in the swap router. /// @dev The calling address must approve this contract to spend at least `amountIn` worth of its WMATIC for this function to succeed. /// @param amountIn The exact amount of WMATIC that will be swapped for WETH. /// @return amountOut The amount of WETH received. function swapExactInputSingle(uint256 amountIn) external returns (uint256 amountOut) { // msg.sender must approve this contract // Transfer the specified amount of WMATIC to this contract. TransferHelper.safeTransferFrom(WMATIC, msg.sender, address(this), amountIn); // Approve the router to spend WMATIC. TransferHelper.safeApprove(WMATIC, address(swapRouter), amountIn); // Naively set amountOutMinimum to 0. In production, use an oracle or other data source to choose a safer value for amountOutMinimum. // We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount. ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({ tokenIn: WMATIC, tokenOut: WETH, fee: poolFee, recipient: msg.sender, deadline: block.timestamp, amountIn: amountIn, amountOutMinimum: 0, sqrtPriceLimitX96: 0 }); // The call to `exactInputSingle` executes the swap. amountOut = swapRouter.exactInputSingle(params); } /// @notice swapExactOutputSingle swaps a minimum possible amount of WMATIC for a fixed amount of WETH. /// @dev The calling address must approve this contract to spend its WMATIC for this function to succeed. As the amount of input WMATIC is variable, /// the calling address will need to approve for a slightly higher amount, anticipating some variance. /// @param amountOut The exact amount of WETH to receive from the swap. /// @param amountInMaximum The amount of WMATIC we are willing to spend to receive the specified amount of WETH. /// @return amountIn The amount of WMATIC actually spent in the swap. function swapExactOutputSingle(uint256 amountOut, uint256 amountInMaximum) external returns (uint256 amountIn) { // Transfer the specified amount of WMATIC to this contract. TransferHelper.safeTransferFrom(WMATIC, msg.sender, address(this), amountInMaximum); // Approve the router to spend the specifed `amountInMaximum` of WMATIC. // In production, you should choose the maximum amount to spend based on oracles or other data sources to acheive a better swap. TransferHelper.safeApprove(WMATIC, address(swapRouter), amountInMaximum); ISwapRouter.ExactOutputSingleParams memory params = ISwapRouter.ExactOutputSingleParams({ tokenIn: WMATIC, tokenOut: WETH, fee: poolFee, recipient: msg.sender, deadline: block.timestamp, amountOut: amountOut, amountInMaximum: amountInMaximum, sqrtPriceLimitX96: 0 }); // Executes the swap returning the amountIn needed to spend to receive the desired amountOut. amountIn = swapRouter.exactOutputSingle(params); // For exact output swaps, the amountInMaximum may not have all been spent. // If the actual amount spent (amountIn) is less than the specified maximum amount, we must refund the msg.sender and approve the swapRouter to spend 0. if (amountIn < amountInMaximum) { TransferHelper.safeApprove(WMATIC, address(swapRouter), 0); TransferHelper.safeTransfer(WMATIC, msg.sender, amountInMaximum - amountIn); } } }
I'm in the same point as you since two weeks. I don't solved the problem yet but I have more data useful for you:
I tried to do a swap on https://app.uniswap.org on mumbai.network and I discovered that the SwapRouter address for mumbai maybe is wrong or is not the primary as they have on official uniswap website (I mean: 0xE592427A0AEce92De3Edee1F18E0157C05861564).
I don't know if they are using two addresses, but I tried two times and two times has passed for 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45 as SwapRouter. You can check it if you try to do a swap on the website.
My tx example: https://mumbai.polygonscan.com/tx/0xa7e75b78ec8f5ae311d0252d0ad7412176ebe7f063df72a8f2c347543f8f2103
ok, finally after several days I achieved do a swap on mumbai with exactInputSingle. This test swap 0.5Wmatic for weth: I attach you my scripts:
TestSwap.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.7.6;
pragma abicoder v2;
import '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';
import "./SwapRouter02lib/ISwapRouter02.sol";
import "./SwapRouter02lib/IV3SwapRouter.sol";
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
contract TestSwap {
using LowGasSafeMath for uint256;
ISwapRouter02 public immutable uniswapRouter;
constructor(address _uniswapRouter) {
uniswapRouter = ISwapRouter02(_uniswapRouter);
}
function swapUniswap(
address token0,
address token1,
uint256 amount,
uint256 fee
) external returns (uint256 amountOut) {
require(IERC20(token0).transferFrom(msg.sender, address(this), amount),"STF v2");
require(IERC20(token0).approve(address(uniswapRouter), amount),"SA v2");
uint256 amountMin = LowGasSafeMath.add(amount, fee);
IV3SwapRouter.ExactInputSingleParams memory params = IV3SwapRouter.ExactInputSingleParams({
tokenIn: token0,
tokenOut: token1,
fee: uint24(fee),
recipient: msg.sender,
amountIn: amount,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
});
(bool success, bytes memory amountBytes) = address(uniswapRouter).call(
abi.encodeWithSelector(
IV3SwapRouter.exactInputSingle.selector,
params
)
);
return bytesToUint(amountBytes);
}
function bytesToUint(bytes memory _bytes) internal pure returns (uint256 value) {
assembly {
value := mload(add(_bytes, 0x20))
}
}
}
deploy-test.js
const hre = require('hardhat');
const ethers = hre.ethers;
const { abi: abiERC20 } = require("../artifacts/contracts/IERC20.sol/IERC20.json");
const uniswapRouter = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"; //ROUTER 02
const uniswapFactory = "0x1F98431c8aD98523631AE4a59f267346ea31F984"; //FACTORY
const wmatic = "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889"; //wmatic mumbai
const weth = "0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa"; //weth mumbai
const fee1 = 500;
const signerAddress = "0x1234567890123456789012345678901234567890";//this must be one of your address with wmatic tokens (I tested on mumbai)
async function main() {
await hre.network.provider.request({
method: 'hardhat_impersonateAccount',
params: [signerAddress],
});
const signer = await ethers.provider.getSigner(signerAddress);
var wmaticContract = new ethers.Contract(
wmatic,
abiERC20,
signer
);
var wethContract = new ethers.Contract(
weth,
abiERC20,
signer
);
const TestSwap = await ethers.getContractFactory("TestSwap");
const testSwap = await TestSwap.deploy(
uniswapRouter
);
await testSwap.deployed();
console.log((await wmaticContract.balanceOf(signer._address)).toString());
console.log((await wethContract.balanceOf(signer._address)).toString());
console.log((await wmaticContract.balanceOf(testSwap.address)).toString());
console.log((await wethContract.balanceOf(testSwap.address)).toString());
const amountApprove = ethers.utils.parseEther('1');
const amount = ethers.utils.parseEther('0.5');
const GAS_PARAMS = {
gasLimit: "1250000",//exagerate amount of gas, must be adjusted
gasPrice: ethers.utils.parseUnits('100','gwei').toString(),
};
const txApproveWMatic = await wmaticContract.connect(signer).approve(
testSwap.address,
amountApprove,
GAS_PARAMS);
await txApproveWMatic.wait();
const tx = await testSwap.connect(signer).swapUniswap(
wmatic,
weth,
amount,
fee1,
GAS_PARAMS
);
console.log(tx);
const txResponse = await tx.wait();
console.log(txResponse);
console.log((await wmaticContract.balanceOf(signer._address)).toString());
console.log((await wethContract.balanceOf(signer._address)).toString());
console.log((await wmaticContract.balanceOf(testSwap.address)).toString());
console.log((await wethContract.balanceOf(testSwap.address)).toString());
}
main();
To run it:
$ npx hardhat run scripts/deploy-test.js
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.