UniswapV2 swapExactETHForTokens method fails with error status 'UniswapV2: TRANSFER_FAILED' - node.js

I am using web3.js library and I am trying to buy a token by calling swapExactETHForTokens method from
UniswapV2Router02 smart contract, but I don't know why my transaction fails. I approved WETH for this transaction, but still get an error with the following status:
Fail with error 'UniswapV2: TRANSFER_FAILED'
My code:
const swapTokens = async () => {
const PRIVATE_KEY = 'my private key goes here';
web3.eth.accounts.wallet.add(PRIVATE_KEY);
const myAccount = web3.eth.accounts.wallet[0].address;
const WETHAddress = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2';
const swapRouterAddress = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D';
const routerContract = new web3.eth.Contract(
UNISWAP_V2_ROUTER_ABI,
swapRouterAddress,
);
const tokenToBuyAddress = '0x0913dDAE242839f8995c0375493f9a1A3Bddc977';
const deadline = Math.floor(Date.now() / 1000) + 60 * 20;
const block = await web3.eth.getBlock('latest');
const gasLimit = Math.round(block.gasLimit / block.transactions.length);
const amountToBuy = 0.01;
const result = await routerContract.methods
.swapExactETHForTokens(
web3.utils.toHex(0),
[WETHAddress, tokenToBuyAddress],
myAccount,
deadline,
)
.send({
from: myAccount,
gasLimit,
value: web3.utils.toWei(`${amountToBuy}`, 'ether'),
});
console.log('result: ', result);
}
swapTokens();
Transaction details on etherscan: https://etherscan.io/tx/0x4c6f507ed95b2889bdb929a34dbbe0114db168c2462ce21778eeed9dc4a894eb
Smart contract of token which I am trying to buy: https://etherscan.io/address/0x0913dDAE242839f8995c0375493f9a1A3Bddc977#code

Your transaction ran out of gas. Increase your gas limit

Related

Uniswap V3 AlphaRouter - "Failed to get subgraph pools from any providers"

I am trying to swap WETH against MyToken from a previously created Uniswap V3 pool on Arbitrum Rinkeby. When calling AlphaRouter.route, however, I get the following error message
Failed to get subgraph pools from any providers
What is still missing to swap?
What do I need to create?
My target is to swap WETH for a given output of MyToken.
I am trying to simply get a swap on Uniswap V3 with my pool done. Any ideas?
const Web3 = require('web3');
const {
ethers
} = require("ethers");
const HDWalletProvider = require('#truffle/hdwallet-provider');
const {
Token,
CurrencyAmount,
TradeType,
Percent
} = require("#uniswap/sdk-core");
const {
AlphaRouter
} = require('#uniswap/smart-order-router');
const ABI_UNISWAP_POOL_V3 = require("#uniswap/v3-core/artifacts/contracts/interfaces/IUniswapV3Pool.sol/IUniswapV3Pool.json");
const fs = require('fs');
const JSBI = require('JSBI');
const API_ALCHEMY_ARBITRUM_RINKEBY = 'https://arb-rinkeby.g.alchemy.com/v2/<API KEY>';
const POOL_ADDRESS_MYTOKEN_WETH = '0xc69e7AE1073DD8184FcF6dBfc27ba97d1524716A';
const mnemonic = fs.readFileSync("./.mnemonics").toString().trim();
const hdprovider = new HDWalletProvider(mnemonic, API_ALCHEMY_ARBITRUM_RINKEBY);
const provider = new ethers.providers.Web3Provider(hdprovider);
const owner = hdprovider.addresses[0];
var web3 = new Web3(hdprovider);
const Contract = web3.eth.Contract;
const router = new AlphaRouter({
chainId: 421611,
provider: provider
});
async function main() {
const MyPool = new Contract(ABI_UNISWAP_POOL_V3.abi, POOL_ADDRESS_MYTOKEN_WETH);
const [factory, token0, token1, fee, tickSpacing, liquidity, maxLiquidityPerTick] =
await Promise.all([MyPool.methods.factory().call(),
MyPool.methods.token0().call(),
MyPool.methods.token1().call(),
MyPool.methods.fee().call(),
MyPool.methods.tickSpacing().call(),
MyPool.methods.liquidity().call(),
MyPool.methods.maxLiquidityPerTick().call()
]);
const tokenA = new Token(3, token0, 2, "MTK", "MyToken");
const tokenB = new Token(3, token1, 18, "WETH", "Wrapped Ether");
var amountOut = 2000;
amountOut = CurrencyAmount.fromRawAmount(tokenA, JSBI.BigInt(amountOut.toString()));
const slippageTolerance = new Percent(5, 100);
const deadline = Date.now() + 15000;
const route = await router.route(
amountOut,
tokenB,
TradeType.EXACT_OUTPUT, {
recipient: owner,
slippageTolerance: slippageTolerance,
deadline: deadline
}
);
hdprovider.engine.stop();
}
main();
I see two things are not right in this code:
First is the amountOut that you are passing to router.route should be converted to wei
const amountOutInWei=ethers.utils.parseUnits(amountOut.toString(),decimals)
// amountOutInWei should be converted to currentAmount
const currencyAmount= CurrencyAmount.fromRawAmount(tokenA,JSBI.BigInt(amountOutInWei))
currencyAmount should be passed to the router.route(currencyAmount,..)
Second issue deadline must be in seconds.
const deadline=Math.floor(Date.now() / 1000)+10*60 // addded 10 minutes

Sending ERC-20 tokens fails. Transaction succeeds, but no tokens are sent

When I run the following code, it accurately gets the token balance for both addresses and the transaction even goes through (I can see it on the testnet), although no tokens are sent.
I've tried a variety of things including replacing the signed transaction piece with this:
await contract.methods.transfer(toAddress, 100000).send({
from: fromAddress
});
but that fails with an unknown account error.
My Code for sending tokens:
const Web3 = require("web3");
const { hdkey } = require("ethereumjs-wallet");
const bip39 = require("bip39");
const token = require("./token.json");
const mnemonic = "12 word phrase";
const provider = "https://apis.ankr.com/.../binance/full/test";
(async() => {
try {
const seed = await bip39.mnemonicToSeed(mnemonic);
const root = hdkey.fromMasterSeed(seed);
const web3 = new Web3(provider);
const addrNode = root.derivePath(`m/44'/60'/0'/0/0`);
const wallet = addrNode.getWallet();
// #0 in the hdwallet, the owner of the tokens
const fromAddress = wallet.getAddressString();
// #1 in the hdwallet, already has a token balance
const toAddress = "0x...";
const contract = new web3.eth.Contract(token.abi, token.contract_address);
let fromAddressBalance = await contract.methods.balanceOf(fromAddress).call();
let toAddressBalance = await contract.methods.balanceOf(toAddress).call();
console.log(`Pre Transaction: Sender: ${fromAddressBalance} TOKENS / Wallet: ${toAddressBalance} TOKENS`);
// token has 3 decimal places, this is 100.000
const encodedABI = contract.methods.transfer(toAddress, 100000).encodeABI();
const tx = {
from: fromAddress,
to: toAddress,
gas: 2000000,
value: 0x0,
data: encodedABI
};
const signed = await web3.eth.accounts.signTransaction(tx, wallet.privateKey.toString("hex"));
const trans = await web3.eth.sendSignedTransaction(signed.rawTransaction);
fromAddressBalance = await contract.methods.balanceOf(fromAddress).call();
toAddressBalance = await contract.methods.balanceOf(toAddress).call();
console.log(`Post Transaction: Sender: ${fromAddressBalance} TOKENS / Wallet: ${toAddressBalance} TOKENS`);
} catch (err) {
console.error(err.stack);
}
process.exit();
})();
There were a few things wrong that once fixed resolved my issue. I haven't gone back through and tested which did it, or if all were required, but wanted to leave this for future explorers.
I was creating a wallet with ethereum-js-wallet, and then using it with web3. You have to let web3 know about the wallet.
const account = web3.eth.accounts.privateKeyToAccount(privateKey);
web3.eth.accounts.wallet.create();
web3.eth.accounts.wallet.add(account);
Private key addresses need to start with 0x.
Source: https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#privatekeytoaccount
const privateKey = `0x${wallet.privateKey.toString("hex")}`;
This ended up not mattering, and not being the correct way to transfer, but it's still a good note that I was sending a signed transaction to a 3rd party, NOT to the contract, the correct way to send the transaction would have been
const tx = {
from: fromAddress,
to: token.contract_address,
gas: 2000000,
value: 0x0,
data: encodedABI
};
Ultimately, I needed to take advantage of the contract's transfer method vs signing/sending a transaction
const result = await contract.methods.transfer(toAddress, 100).send({
from: fromAddress,
gas: 2000000
});

I’m trying to execute swap on Pancakeswap with node script but I get error

I am new at ethereum development and I am working on a simple script to execute swaps using Pancakeswap.
The code:
const ethers = require('ethers');
const {ChainId, Token, TokenAmount, Fetcher, Pair, Route, Trade, TradeType, Percent} =
require('#pancakeswap-libs/sdk');
const Web3 = require('web3');
const {JsonRpcProvider} = require("#ethersproject/providers");
require("dotenv").config();
const provider = new JsonRpcProvider('https://bsc-dataseed1.binance.org/');
const web3 = new Web3('wss://apis.ankr.com/wss/c40792ffe3514537be9fb4109b32d257/946dd909d324e5a6caa2b72ba75c5799/binance/full/main');
const { address: admin } = web3.eth.accounts.wallet.add(process.env.PRIVATE_KEY);
console.log(`Modulos cargados`);
// Command Line Input
const InputTokenAddr = web3.utils.toChecksumAddress(process.argv[2]);
// var BUSD = '0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56';
const OutputTokenAddr = web3.utils.toChecksumAddress(process.argv[3]);
// var WBNB = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c';
const InputTokenAmount = process.argv[4]
const Slipage = process.argv[5];
const PANCAKE_ROUTER = process.argv[6];
// const PANCAKE_ROUTER_V2 = '0x10ed43c718714eb63d5aa57b78b54704e256024e';
// const PANCAKE_ROUTER_V1 = '0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F';
// 1/1000 = 0.001
const ONE_ETH_IN_WEI = web3.utils.toBN(web3.utils.toWei('1'));//BN->(BIG NUMBER) || toWei -> Converts any ether value value into wei.
const tradeAmount = ONE_ETH_IN_WEI.div(web3.utils.toBN('1000'));//tradeAmount = ONE_ETH_IN_WEI/1000
console.log(`tradeAmount ` + tradeAmount );
const init = async () => {
const [INPUT_TOKEN, OUTPUT_TOKEN] = await Promise.all(
[InputTokenAddr, OutputTokenAddr].map(tokenAddress => (
new Token(
ChainId.MAINNET,
tokenAddress,
18
)
)));
console.log(` <<<<<------- pair-------->>>>>`);
const pair = await Fetcher.fetchPairData(INPUT_TOKEN, OUTPUT_TOKEN, provider);
//console.log(JSON.stringify(pair));
console.log(` <<<<<------- route-------->>>>>`);
const route = await new Route([pair], INPUT_TOKEN);
//console.log(JSON.stringify(route));
console.log(` <<<<<------- Trade-------->>>>>`);
const trade = await new Trade(route, new TokenAmount(INPUT_TOKEN, tradeAmount), TradeType.EXACT_INPUT);
//console.log(JSON.stringify(trade));
//https://uniswap.org/docs/v2/javascript-SDK/trading/
const slippageTolerance = new Percent(Slipage, '100'); //
console.log("slippageTolerance: " + JSON.stringify(slippageTolerance));
// create transaction parameters
const amountOutMin = trade.minimumAmountOut(slippageTolerance).raw;
const path = [INPUT_TOKEN.address, OUTPUT_TOKEN.address];
const to = admin;
const deadline = Math.floor(Date.now() / 1000) + 60 * 20;
// Create signer
const wallet = new ethers.Wallet(
Buffer.from(
process.env.PRIVATE_KEY,
"hex"
)
);
const signer = wallet.connect(provider);
// Create Pancakeswap ethers Contract
const pancakeswap = new ethers.Contract(
PANCAKE_ROUTER,
['function swapExactTokensForTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts)'],
signer
);
//Allow input token
if(true)
{
console.log(`Allow Pancakeswap <<<<<------- START-------->>>>>`);
let abi = ["function approve(address _spender, uint256 _value) public returns (bool success)"];
let contract = new ethers.Contract(INPUT_TOKEN.address, abi, signer);
let aproveResponse = await contract.approve(PANCAKE_ROUTER, ethers.utils.parseUnits('1000.0', 18), {gasLimit: 100000, gasPrice: 5e9});
console.log(JSON.stringify(aproveResponse));
console.log(`Allow Pancakeswap <<<<<------- END-------->>>>>`);
}
if(true)
{
console.log(`Ejecutando transaccion`);
var amountInParam = ethers.utils.parseUnits(InputTokenAmount, 18);
var amountOutMinParam = ethers.utils.parseUnits(web3.utils.fromWei(amountOutMin.toString()), 18);
console.log("amountInParam: " + amountInParam);
console.log("amountOutMinParam: " + amountOutMinParam);
console.log("amountOutMin: " + amountOutMin);
const tx = await pancakeswap.swapExactTokensForTokens(
amountInParam,
amountOutMinParam,
path,
to,
deadline,
{ gasLimit: ethers.utils.hexlify(300000), gasPrice: ethers.utils.parseUnits("9", "gwei") }
);
console.log(`Tx-hash: ${tx.hash}`)
const receipt = await tx.wait();
console.log(`Tx was mined in block: ${receipt.blockNumber}`);
}
}
init();
Normally I set BUSD as input token
And I use pancakeswap v1 or v2 router as router.
When output token is WBNB or BCH, it seems working well on both v1 and v2 router.
But when I set other token as an output token, I get error.
Plz help me.

Rinkeby Uniswap swapExactETHForTokens - Fail with error 'UniswapV2Router: EXPIRED'

Ideally, I need example of correct transaction format in web3 or ethers,
Where it can swap WETH for ERC20 or ERC20 for WETH using UniswapV2Router on Rinkeby,
I think, I'm having wrong transaction format, maybe it's because of gasPrice or gasLimit, but I don't understand where it happens, So I tried with the increased gasPrice(100 Gwei) and gasLimit(8,000,000) but it's still failing, I also decreased the "amountOutMin" to 1,
Transaction deadline is 20 minutes but it's failiing in a few seconds
Swap 1 Ether for UNI (WETH and ETH balances are more than 5 on sender's address)
transaction deadline: 20 minute
UNI address: 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984
UniswapV2Router: 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
Another small question, when you swap ETH for ERC20 does it takes WETH or ETH from senders balance?
const swap = async () => {
try{
const chainId = ChainId.RINKEBY
const tokenAddress = "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"
const uni = await Fetcher.fetchTokenData(chainId, tokenAddress)
const weth = WETH[chainId]
const pair = await Fetcher.fetchPairData(uni, weth)
const route = new Route([pair], weth)
const trade = new Trade(route, new TokenAmount(weth, '100000000000000000'), TradeType.EXACT_INPUT)
console.log('1 WETH for', route.midPrice.toSignificant(6), ' UNI')
console.log('1 UNI for', route.midPrice.invert().toSignificant(6), ' WETH')
console.log('Trade price 1 WETH for ', trade.executionPrice.toSignificant(6), ' UNI')
const accounts = await web3.eth.getAccounts()
const account = accounts[0]
const slippageTolerance = new Percent('20', '100')
const path = [weth.address, uni.address ]
const to = account
// function toHex(currencyAmount) {
// return `0x${currencyAmount.raw.toString(16)}`
// }
// const amountOutMin = toHex(trade.minimumAmountOut(slippageTolerance))
// const value = toHex(trade.inputAmount)
const uniswap = await new web3.eth.Contract(abi, "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D")
const now = moment().unix()
const DEADLINE = now + 60 *20
console.log('Sending...')
let txn = await uniswap.methods.swapExactETHForTokens( 1, path, to, DEADLINE ).send( {
from: account,
gasLimit: 8000000,
gasPrice: web3.utils.toWei('100', 'Gwei'),
value: web3.utils.toWei('1', 'Ether')
})
console.log(`Txn: https://rinkeby.etherscan.io/tx/${txn.transactionHash}`)
}catch(e){
console.log(e)
}
}
module.exports = swap
Transaction results on rinkeby etherscan:
Console:
"Error: Transaction has been reverted by the EVM "
Here is an example of swapping ETH to UNI. I am using ethJS.
const WETH_ADDRESS = "0xc778417e063141139fce010982780140aa0cd5ab";
const UNI_ADDRESS = "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984";
const path = [WETH_ADDRESS, UNI_ADDRESS];
const ethAmount = ethers.utils.parseEther("0.1");
const nowInSeconds = Math.floor(Date.now() / 1000)
const expiryDate = nowInSeconds + 900;
const txn = await uniswapV2Contract.swapExactETHForTokens(
0,
path,
user.address,
expiryDate,
{
gasLimit: 1000000,
gasPrice: ethers.utils.parseUnits("10", "gwei"),
value: ethAmount
}
)
const res = await txn.wait();
When you call the method swapExactETHForTokens, it would be taking ETH and not WETH. If you would like to swap with WETH, you should call swapExactTokensForTokens.

Sending a transaction results in "invalid sender"

I'm attempting to call a function on my smart contract (Ropsten) using web3 via an Infura node. I've created a test account in Metmask and have exported the account address and private key. The details look correct, however I am getting the error {"code":-32000,"message":"invalid sender"}. I'm guessing this is a problem with the signing of the transaction?
Here's my code
const Web3 = require('web3');
const Tx = require('ethereumjs-tx').Transaction;
const fs = require('fs');
const pk = Buffer.from('PRIVATE KEY FROM METAMASK', 'hex')
const sourceAccount = 'ACCOUNT ADDRESS FROM METAMASK'
const web3 = new Web3(new Web3.providers.HttpProvider("https://ropsten.infura.io/v3/API_KEY"));
const consumerAddress = '0xc36577aa0171f649be6bd7205148ed83c07198ee';
web3.eth.defaultAccount = sourceAccount;
//Get Consumer contract instance
const consumerAbi = JSON.parse(fs.readFileSync('rental-contract-abi.json', 'utf8'));
let consumerContract = new web3.eth.Contract(consumerAbi, consumerAddress);
const myData = consumerContract.methods.checkDate("e716efba3b404da98e28faaa2939c0fd","2019-06-04","AU-NSW").encodeABI();
web3.eth.getTransactionCount(sourceAccount, (err, txCount) => {
// Build the transaction
const txObject = {
nonce: web3.utils.toHex(txCount),
to: consumerAddress,
from: sourceAccount,
chainId: 3,
value: web3.utils.toHex(web3.utils.toWei('0', 'ether')),
gasLimit: web3.utils.toHex(2100000),
gasPrice: web3.utils.toHex(web3.utils.toWei('6', 'gwei')),
data: myData
}
// Sign the transaction
const tx = new Tx(txObject);
tx.sign(pk);
const feeCost = tx.getUpfrontCost()
console.log('Total Amount of ETH needed:' + web3.utils.fromWei(feeCost.toString(), 'ether'))
console.log('---Serialized TX----')
console.log(tx.serialize().toString('hex'))
console.log('--------------------')
const serializedTx = tx.serialize();
const raw = '0x' + serializedTx.toString('hex');
// Broadcast the transaction
const transaction = web3.eth.sendSignedTransaction(raw, (err, tx) => {
console.log(tx);
console.log(err);
});
});
You need to add network information while signing the transaction. Refer to latest web3 docs. Change signing transaction code to :
const tx = new Tx(txObject,{'chain':'ropsten'});

Resources