I'm trying to create a script to execute a swap on Uniswap V3.
The code below works perfectly well on the Goerli Testnet Network but NOT on Mainnet.
In order to make in run on mainnet:
i've changed the tokens addresses to match the mainnet ones and also changed the INFURA_URL to the mainnet url but I keep getting failed transactions..
const address0 = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'
const address1 = '0x6B175474E89094C44Da98b954EedeAC495271d0F'
Seems like the error might come from the swapRouterAddress but not sure..
Moreover, when I execute the swap manually using Uniswap website, i can see that the swap was executed using Uniswap V3: Router 2, but even if I use this Router Address on my script the transaction keep failing..
Does anyone knows how to solve this ?
Thanks a lot !
const { ethers } = require('ethers')
const { abi: IUniswapV3PoolABI } = require('#uniswap/v3-core/artifacts/contracts/interfaces/IUniswapV3Pool.sol/IUniswapV3Pool.json')
const { abi: SwapRouterABI} = require('#uniswap/v3-periphery/artifacts/contracts/interfaces/ISwapRouter.sol/ISwapRouter.json')
const { abi: UniswapV3Factory } = require('#uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json')
const { getPoolImmutables, getPoolState } = require('./helpers')
const ERC20ABI = require('./abi.json')
require('dotenv').config()
const INFURA_URL_TESTNET = process.env.INFURA_URL_TESTNET
// Wallets
const WALLETS = [process.env.WALLET_ADDRESS_1];
var SECRET = new Object();
SECRET[process.env.WALLET_ADDRESS_1] = process.env.WALLET_SECRET_1;
// Provider
const provider = new ethers.providers.JsonRpcProvider(INFURA_URL_TESTNET) // Goerli
const swapRouterAddress = '0xE592427A0AEce92De3Edee1F18E0157C05861564'
// Wrapped Ether
const name0 = 'Wrapped Ether'
const symbol0 = 'WETH'
const decimals0 = 18
const address0 = '0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6'
// Token info
const name1 = 'Token'
const decimals1 = 18
const address1 = '0x11fE4B6AE13d2a6055C8D9cF65c55bac32B5d844' // DAI
// SWAP
const factoryAddress = '0x1F98431c8aD98523631AE4a59f267346ea31F984'
async function buy(WETH_amount) {
const factoryContract = new ethers.Contract(
factoryAddress,
UniswapV3Factory,
provider
)
const poolAddress = await factoryContract.getPool(address0, address1, 500)
for (const WALLET of WALLETS)
{
const poolContract = new ethers.Contract(
poolAddress,
IUniswapV3PoolABI,
provider
)
const immutables = await getPoolImmutables(poolContract)
const state = await getPoolState(poolContract)
var WALLET_SECRET = SECRET[WALLET];
const wallet = new ethers.Wallet(WALLET_SECRET)
const connectedWallet = wallet.connect(provider)
const swapRouterContract = new ethers.Contract(
swapRouterAddress,
SwapRouterABI,
provider
)
const inputAmount = WETH_amount
// .001 => 1 000 000 000 000 000
const amountIn = ethers.utils.parseUnits(
inputAmount.toString(),
decimals0
)
const params = {
tokenIn: immutables.token1,
tokenOut: immutables.token0,
fee: immutables.fee,
recipient: WALLET,
deadline: Math.floor(Date.now() / 1000) + (60 * 5),
amountIn: amountIn,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0,
}
const transaction = swapRouterContract.connect(connectedWallet).exactInputSingle(
params,
{
gasLimit: ethers.utils.hexlify(1000000)
}
).then(transaction => {
console.log(transaction)
})
}
}
// MAIN
buy(WETH_amount_=0.001)
Note that the token address for WETH is different on mainnet - your code has the address for WETH on Goerli. See https://docs.uniswap.org/protocol/reference/deployments for some token addresses
I have a problem calling a read only function from my frontend. When I try to call it metamask ask me to pay gas fee
and the output of this transaction doesn't have any sense.
The solidity smart contract: https://rinkeby.etherscan.io/address/0xcf781c136ce1534d00db67c4ec488a6c4e01bbef
This is the solidity function : viewregistro
function compile_registro (string memory new_reg) public returns (bool registration){
registro[ultima] = new_reg;
ultima = ultima +1;
registration = true;
return registration;
}
function viewregistro(uint where) public view returns (string memory here){
here = registro[where];
return here;
}
This is the javascript code:
const enable = async () =>{
await window.ethereum.enable();
provider = new ethers.providers.Web3Provider(window.ethereum);
signer = await provider.getSigner();
address = await signer.getAddress();
console.log(provider);
return provider, signer, address
}
const contractConnection2 = async () => {
rank = new ethers.Contract( address_, rankingabi_ ,signer);
console.log(rank);
return rank;
}
const addmember = async() => {
rank.compile_registro("pluto");
}
Trying to exchange USDC to ETH vith Uniswap and Ethers, but getting errors all the time.
async function swapUsdcToEth(amount, walledAddress) {
const usdc = await Fetcher.fetchTokenData(chainId, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48');
const eth = await Fetcher.fetchTokenData(chainId, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2');
const pair = await Fetcher.fetchPairData(usdc, eth);
const route = new Route([pair], usdc);
const amountIn = new TokenAmount(usdc, amount);
const trade = new Trade(route, amountIn, TradeType.EXACT_INPUT);
const slippageTolerance = new Percent('50', '10000');
const value = ethers.BigNumber.from(trade.inputAmount.raw.toString()).toHexString();
const amountOutMin = ethers.BigNumber.from(trade.minimumAmountOut(slippageTolerance).raw.toString()).toHexString();
const deadline = Math.floor(Date.now() / 1000) + 60 * 20;
const uniswapRouterV2Address = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D';
const provider = new ethers.providers.JsonRpcProvider('https://mainnet.infura.io/v3/b9fkdmkdkdv4937b52ea9637cf1d1bd');
const signer = new ethers.Wallet(walledAddress, provider);
const uniswap = new ethers.Contract(
uniswapRouterV2Address,
['function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts)'],
signer
);
try {
const tx = await uniswap.swapExactTokensForETH(value, amountOutMin, [walledAddress], walledAddress, deadline);
const receipt = await tx.wait();
console.log('transaction was mined in block', receipt.blockNumber);
} catch (e) {
console.log(e);
}
}
Receiving errors like that: ' Error: cannot estimate gas; transaction may fail or may require manual gas limit '. What I am doing wrong?
So it looks like possibly a few things. Have you approved your token to be spent by the router?
Also I'm not seeing any gas settings in there
here is a working version that I have modified to make work ( This is setup to test on a mainnet fork, however it's using live data (as the AlphaRouter is only for mainnet live so the live data and the fork data will change with time and cause trade errors, so reset fork before using)
to make main net only take out local provider and change all providers to main net provider.
USE WITH CAUTION, I'M NOT PERFECT AND GUARANTEE NOTHING : Check slippage and all variables
This is built As a TOKEN to TOKEN Exact_Input swap with WETH deposit of 1 ETH.
To use ETH you can remove Weth deposit and token in approval and use the BigNumber.from(typedValueParsed) as the value of the transaction instead of 0
As I don't know EtherJS to well the Gas Price and Gas Limit for the Deposit and approval is a flat 100 gwei & 300k Limit, and should be modified for current network gas price and estimated gas Limit.
import { AlphaRouter } from '#uniswap/smart-order-router'
import { Token, CurrencyAmount } from '#uniswap/sdk-core'
import { JSBI, Percent } from "#uniswap/sdk";
import { ethers, BigNumber } from "ethers";
const V3_SWAP_ROUTER_ADDRESS = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45";
const TokenInput = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
const TokenOutput = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
const web3Provider = new ethers.providers.JsonRpcProvider("https://eth-mainnet.alchemyapi.io/v2/");
const web3 = new ethers.providers.JsonRpcProvider("http://127.0.0.1:8545/");
const privateKey = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
const wallet = new ethers.Wallet(privateKey,web3);
const address = wallet.address;
import * as fs from 'fs';
let UniV3RouterAbi = fs.readFileSync('NewUniRouter.json');
const V3routerAbi = JSON.parse(UniV3RouterAbi);
let ERC20Abi = fs.readFileSync('ERC20.json');
const ERC20 = JSON.parse(ERC20Abi);
let WETHAbij = fs.readFileSync('WETHAbi.json');
const WETHAbi = JSON.parse(WETHAbij);
async function log(inpt){
console.log(inpt);
console.log("");
}
async function TokBal(tokens){
var ERC20contract = new ethers.Contract(tokens, ERC20, web3);
var myERC20bal = await ERC20contract.balanceOf(wallet.address);
return myERC20bal;
}
async function Deposit(amt){
var WethC = new ethers.Contract(TokenInput, WETHAbi, web3);
var datac = await WethC.populateTransaction["deposit"]();
var ncn = await wallet.getTransactionCount();
const transaction = {
data: datac.data,
nonce: ncn,
to: TokenInput,
value: BigNumber.from(amt),
from: wallet.address,
gasPrice: '0x174876e800',
gasLimit: '0x493e0',
};
const signedTx = await wallet.signTransaction(transaction);
const txHash = await web3.sendTransaction(signedTx);
log(txHash.hash);
}
async function Approve(Toked, amt){
var WethC = new ethers.Contract(Toked, ERC20, web3);
var datac = await WethC.populateTransaction["approve"](V3_SWAP_ROUTER_ADDRESS, amt);
var ncn = await wallet.getTransactionCount();
const transaction = {
data: datac.data,
nonce: ncn,
to: Toked,
value: BigNumber.from("0"),
from: wallet.address,
gasPrice: '0x174876e800',
gasLimit: '0x493e0',
};
const signedTx = await wallet.signTransaction(transaction);
const txHash = await web3.sendTransaction(signedTx);
log(txHash.hash);
var appFor = await WethC.callStatic.allowance(wallet.address, V3_SWAP_ROUTER_ADDRESS);
log("Approved : "+appFor.toString());
}
const router = new AlphaRouter({ chainId: 1, provider: web3Provider });
const WETH = new Token(
router.chainId,
'0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
18,
'WETH',
'Wrapped Ether'
);
const USDC = new Token(
router.chainId,
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
6,
'USDC',
'USD//C'
);
const typedValueParsed = '1000000000000000000';
const wethAmount = CurrencyAmount.fromRawAmount(WETH, JSBI.BigInt(typedValueParsed));
const IO = "Exact_Input"
const TradeType = IO == "Exact_Input" ? 0 : 1;
const route = await router.route(
wethAmount,
USDC,
TradeType,
{
recipient: wallet.address,
slippageTolerance: new Percent(5, 100),
deadline: Math.floor(Date.now()/1000 +1800)
}
);
var Ebal = await web3.getBalance(wallet.address);
log("Wallet Balance : "+Ebal.toString());
var tbal = await TokBal(TokenOutput);
log("Token Out Balance : "+tbal.toString());
await Deposit("1000000000000000000");
await Approve(TokenInput,"1000000000000000000");
var tbalW = await TokBal(TokenInput);
log("Token In Balance : "+tbalW.toString());
log(`Quote Exact In: ${route.quote.toFixed(wethAmount.currency === WETH ? USDC.decimals : WETH.decimals)}`);
log(`Gas Adjusted Quote In: ${route.quoteGasAdjusted.toFixed(wethAmount.currency === WETH ? USDC.decimals : WETH.decimals)}`);
var nc = await wallet.getTransactionCount();
const transaction = {
data: route.methodParameters.calldata,
nonce: nc,
to: V3_SWAP_ROUTER_ADDRESS,
value: BigNumber.from(0),
from: wallet.address,
gasPrice: BigNumber.from(route.gasPriceWei),
gasLimit: BigNumber.from(route.estimatedGasUsed).add(BigNumber.from("50000")),
};
const signedTx = await wallet.signTransaction(transaction);
const PretxHash = ethers.utils.keccak256(signedTx);
const txHash = await web3.sendTransaction(signedTx)
log(txHash.hash);
var Ebal = await web3.getBalance(wallet.address);
log("Wallet Balance : "+Ebal.toString());
var tbal = await TokBal(TokenOutput);
log("Token Out Balance : "+tbal.toString());
var tbalW = await TokBal(TokenInput);
log("Token In Balance : "+tbalW.toString());
to get ETH use this in place of the output token
outPutAddress === WETH9[chainId].address ? nativeOnChain(chainId) : outPutToken,
EDIT>>>>>>>>>>
modified for new versions
import { ethers } from 'ethers'
import {AlphaRouter, ChainId, SwapType, nativeOnChain} from '#uniswap/smart-order-router'
import { TradeType, CurrencyAmount, Percent, Token } from '#uniswap/sdk-core'
import { TickMath } from '#uniswap/v3-sdk';
import JSBI from 'jsbi';
import bn from 'bignumber.js'
async function main() {
const MY_ADDRESS = "<ADDRESS>";
const web3Provider = new ethers.providers.JsonRpcProvider('https://eth-mainnet.alchemyapi.io/v2/<RPC_KEY>')
const router = new AlphaRouter({ chainId: 1, provider: web3Provider });
const WETH = new Token(
1,
'0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
18,
'WETH',
'Wrapped Ether'
);
const USDC = new Token(
ChainId.MAINNET,
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
6,
'USDC',
'USD//C'
);
const AAVE = new Token(
ChainId.MAINNET,
'0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9',
18,
'AAVE',
'AAVE'
);
const options = {
recipient: MY_ADDRESS,
slippageTolerance: new Percent(10, 1000),
deadline: Math.floor(Date.now() / 1000 + 1800),
type: SwapType.SWAP_ROUTER_02,
}
const typedValueParsed = '10000000000000000000'
const route = await router.route(
CurrencyAmount.fromRawAmount(
AAVE,
typedValueParsed.toString()
),
nativeOnChain(ChainId.MAINNET),
TradeType.EXACT_INPUT,
options
)
console.log(`Quote Exact In: ${route.quote.toFixed(route.quote.currency.decimals)}`);
console.log(`Gas Adjusted Quote In: ${route.quoteGasAdjusted.toFixed(route.quote.currency.decimals)}`);
console.log(`Gas Used USD: ${route.estimatedGasUsedUSD.toFixed(2)}`);
console.log(route.methodParameters.calldata);
}
main()
Hello I am new to Smart Contract development, for a few days I try to get this working, but no luck. I hope someone can help me. I try to communicate to a Smart Contract deployed to BSC https://testnet.bscscan.com/address/0x2ED1c3c1Fc6646F321cf546a892684E946435CE9 see the source code below.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "#chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract FundMe {
mapping(address => uint256) public addressToAmountFunded;
address[] public funders;
address public owner;
AggregatorV3Interface internal priceFeed;
uint balance;
// if you're following along with the freecodecamp video
// Please see https://github.com/PatrickAlphaC/fund_me
// to get the starting solidity contract code, it'll be slightly different than this!
constructor(address _priceFeed) {
priceFeed = AggregatorV3Interface(_priceFeed);
owner = msg.sender;
}
function fund() public payable {
uint256 mimimumUSD = 50 * 10**18;
require(
getConversionRate(msg.value) >= mimimumUSD,
"You need to spend more ETH!"
);
addressToAmountFunded[msg.sender] += msg.value;
balance += msg.value;
funders.push(msg.sender);
}
function getVersion() public view returns (uint256) {
return priceFeed.version();
}
function getPrice() public view returns (uint256) {
(, int price, , , ) = priceFeed.latestRoundData();
return uint256(price * 10000000000);
}
// 1000000000
function getConversionRate(uint256 ethAmount)
public
view
returns (uint256)
{
uint256 ethPrice = getPrice();
uint256 ethAmountInUsd = (ethPrice * ethAmount) / 1000000000000000000;
return ethAmountInUsd;
}
function getEntranceFee() public view returns (uint256) {
// mimimumUSD
uint256 mimimumUSD = 50 * 10**18;
uint256 price = getPrice();
uint256 precision = 1 * 10**18;
return (mimimumUSD * precision) / price;
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
function withdraw() public payable onlyOwner {
payable(msg.sender).transfer(balance);
for (
uint256 funderIndex = 0;
funderIndex < funders.length;
funderIndex++
) {
address funder = funders[funderIndex];
addressToAmountFunded[funder] = 0;
}
funders = new address[](0);
}
}
I deployed the smart contract with truffle, with the following migration script
const FundMe = artifacts.require("FundMe");
const BINANCE_BNB_USD_PRICE_FEED = '0x0567F2323251f0Aab15c8dFb1967E4e8A7D42aeE';
module.exports = async (deployer, network, [defaultAccount]) => {
let priceFeedAddress = BINANCE_BNB_USD_PRICE_FEED
try {
await deployer.deploy(FundMe, BINANCE_BNB_USD_PRICE_FEED, { from: defaultAccount })
} catch (err) {
console.error(err)
}
}
I try to call getPrice() that communicates to chainlink to get the latest price of BNB/USDT.
Here is the Javascript
const getContract = () =>
new Promise(async (resolve, reject) => {
const contract = await fetch('./build/contracts/FundMe.json')
const Contract = await contract.json()
let provider = await detectEthereumProvider()
if (provider) {
await provider.request({ method: 'eth_requestAccounts' })
const networkId = await provider.request({ method: 'net_version' })
provider = new ethers.providers.Web3Provider(provider)
const signer = provider.getSigner()
showAddress(signer)
const contract = new ethers.Contract(
Contract.networks[networkId].address,
Contract.abi,
signer,
)
resolve(contract)
return
}
reject('Install Metamask')
})
const showAddress = async (signer) => {
address = await signer.getAddress()
const connectButton = document.getElementById('connect')
connectButton.innerText = address
}
const getPrice = async (contract) => {
console.log('contract', contract)
const price = await contract.getPrice()
console.log('price', price)
const priceContainer = document.getElementById('price')
priceContainer.innerText = price
}
const init = async () => {
const contract = await getContract()
getPrice(contract)
}
const fundButton = document.getElementById('fund')
fundButton.addEventListener('click', async () => {
const fundMe = await getContract()
})
init()
I get the following error in the browser console and have no idea whats the cause.
Your deploy script passing the 0x056... address as the priceFeed param of the constructor.
So the getPrice() contract function is then trying to call the latestRoundData() on the 0x056... address, expecting a response.
However, your contract is deployed on the testnet, and there's no contract on the 0x056... address on the testnet (link) to return a value, which causes the "main" call to revert.
I am a beginner in blockchain programming and I am not able to understand why I am getting an error while trying to solidity function using Web3 and Ganache.
const PetList = require('./build/contracts/PetList.json')
const fs = require('fs')
const Web3 = require('web3')
const abi = fs.readFileSync("build/contracts/PetList.json").toString().trim();
// Ganache Blockchain
const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:7545"));
web3.eth.net.isListening()
.then(() => console.log('Web3 is connected'))
.catch(e => console.log('Wow. Something went wrong'));
var setUpContract = async function( ){
await web3.eth.net.getId().then((networkId) => {
const networkData = PetList.networks[networkId]
console.log("Setting up contract...")
if(networkData){
return petList = new web3.eth.Contract(PetList.abi, networkData.address)
}
})
acc = await web3.eth.getAccounts()
currentAccount = acc[0]
console.log("Account: ", acc[0])
}
async function start(){
await setUpContract()
await addPet()
}
var addPet = async function(){
console.log(await getPetCount())
return results = await petList.methods.addPet('Zippo', 'Dog').send({from: currectAccount})
}
start()
pragma solidity ^0.5.0;
contract PetList{
uint public petCount = 0;
mapping (uint => Pet) public pets;
struct Pet{
uint id;
string name;
string tag;
}
event PetAdded(
uint id,
string name,
string tag
);
function addPet(string memory _name, string memory _tag) public {
require(bytes(_name).length > 0, "INVALID TAG");
require(bytes(_tag).length > 0, "INVALID NAME");
petCount++;
pets[petCount] = Pet(petCount, _name, _tag);
emit PetAdded(petCount, _name, _tag);
}
}
I also used .send() without any parameters and it gave me an error saying No "from" address specified in neither the given options, nor the default options.
To make a function receive ether you must have a fallback function or add payable modifier
So you can change your code to the following
function addPet(string memory _name, string memory _tag) public payable