Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set gasLimit and gasPrice on contract transactions #40

Closed
fmsouza opened this issue Oct 24, 2017 · 54 comments
Closed

Set gasLimit and gasPrice on contract transactions #40

fmsouza opened this issue Oct 24, 2017 · 54 comments
Labels
documentation Documentation related issue.

Comments

@fmsouza
Copy link

fmsouza commented Oct 24, 2017

I've been searching in the online documentation for a way to set my gasPrice and gasLimit when creating a transaction on a contract, but couldn't find a way to make it work. I attempted to modify the transaction while signing using a CustomSigner, but didn't had any success.

Is there any way to do it?

@ricmoo
Copy link
Member

ricmoo commented Oct 24, 2017

Good point! I need to update the documentation to include details on this.

Any contract operation can take in one additional (optional) parameter, which is an object of overrides.

function foo(address addr) { ... }
function bar(address addr) constant returns (string result) { ... }

can be called with:

// You can optionally override the following on non-constant functions; anything
// you do not override will be determined automatically
var options = { gasPrice: 1000000000, gasLimit: 85000, nonce: 45, value: 0 };
var fooPromise = contract.foo(address, options);

// You can optionally override the following on constant functions
var options = { from: otherAddress };
var barPromise = contract.bar(address, options);

@fmsouza
Copy link
Author

fmsouza commented Oct 24, 2017

Thanks!

@ricmoo ricmoo added the documentation Documentation related issue. label Oct 26, 2017
@ricmoo
Copy link
Member

ricmoo commented Nov 9, 2017

I've added a small example on the contract non-constant function documentation, but in the documentation overhaul, this will need to have it's own section.

Thanks!

@ricmoo ricmoo closed this as completed Nov 9, 2017
@aakilfernandes
Copy link

Looks like you can also override the getGasPrice function of the provider

if (tx.gasPrice == null) {
tx.gasPrice = provider.getGasPrice();
}

@aakilfernandes
Copy link

aakilfernandes commented Mar 15, 2020

class FastProvider extends ethers.providers.InfuraProvider {
  async getGasPrice() {
    const gasPrice = await super.getGasPrice()
    return gasPrice.add(gasPrice.div(5))
  }
}

careful while doing math with ether's BigNumber. It can't handle decimals

@williamoc74
Copy link

Hi, where do I need to add the above in my code to get this to work?
I've added
class FastProvider extends ethers.providers.InfuraProvider {
async getGasPrice() {
const gasPrice = await super.getGasPrice()
return gasPrice.add(gasPrice.div(5))
}
}

but I'm still getting an error
(node:7820) UnhandledPromiseRejectionWarning: Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"reason":"cannot estimate gas; transaction may fail or may require manual gas limit","code":"UNPREDICTABLE_GAS_LIMIT","error":{"code":3,"response":"{"jsonrpc":"2.0","id":6,"error":{"code":3,"data":

Can anyone guide me in the right direction?

Thanks

@zemse
Copy link
Collaborator

zemse commented May 16, 2021

Hey @williamoc74, if you just want to add a custom gas price and gas limit to your contract transaction:

await contract.yourMethod(arg1, arg2, {gasPrice: ethers.utils.parseUnits('100', 'gwei'), gasLimit: 1000000});

You can also see docs.

The code from aakilfernandes that you are copying is for using 5 times the existing default gas price as the new default price.

@williamoc74
Copy link

Hi @zemse Thank you for the reply.
I'm not to bothered about adding a custom gas price, I just want the contract to run.
I've added the above code but once I add it, it doesn't error, it just runs but doesn't execute anything.

I see you said this else where
The revert is likely because if insufficient msg.value sent to the multisender contract, which tries to send given eth to your target addresses.

const transactionOptions = {
    gasLimit: 6000000,
    gasPrice: ethers.utils.parseUnits('1.0', 'gwei')
    value: ethers.utils.parseEther('3.0') // adding this should fix
}

So I'm going to try this next. If this doesn't work, can I post my code and hopefully we can find a solution that way?
Again, much thanks.. :)

@williamoc74
Copy link

No joy with the above - I even remove the "value...."
and its just the same error as I always get

`New pair detected
=================
token0: 0xb28aba015db622386914adFc505A9583ae588829
token1: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
pairAddress: 0xaBe41D7Da13649b1BEFE1F487363eCB069CA4E35

Buying new token
=================


tokenIn: 10000000000000000 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 (WETH)
tokenOut: 386907351979022469 0xb28aba015db622386914adFc505A9583ae588829

(node:6337) UnhandledPromiseRejectionWarning: Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"reason":"cannot estimate gas; transaction may fail or may require manual gas limit","code":"UNPREDICTABLE_GAS_LIMIT","error":{"code":3,"response":"{"jsonrpc":"2.0","id":6,"error":{"code":3,"data":`

@ricmoo
Copy link
Member

ricmoo commented May 16, 2021

Can you include the full error and your current code? If you are passing gasLimit in, you should not be able to get that error… :s

@williamoc74
Copy link

williamoc74 commented May 16, 2021

Hi Ricmoo..

This is the code

const ethers = require('ethers');

const addresses = {
  WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
  factory: '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f', 
  router: '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
  recipient: '*****'
}

const mnemonic = '*****';

const provider = new ethers.providers.WebSocketProvider('*****');
const wallet = ethers.Wallet.fromMnemonic(mnemonic);
const account = wallet.connect(provider);
const factory = new ethers.Contract(
  addresses.factory,
  ['event PairCreated(address indexed token0, address indexed token1, address pair, uint)'],
  account
);
const router = new ethers.Contract(
  addresses.router,
  [
    'function getAmountsOut(uint amountIn, address[] memory path) public view returns (uint[] memory amounts)',
    'function swapExactTokensForTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts)'
  ],
  account
);

factory.on('PairCreated', async (token0, token1, pairAddress) => {
  console.log(`
    New pair detected
    =================
    token0: ${token0}
    token1: ${token1}
    pairAddress: ${pairAddress}
  `);

  //The quote currency needs to be WETH (we will pay with WETH)
  let tokenIn, tokenOut;
  if(token0 === addresses.WETH) {
    tokenIn = token0; 
    tokenOut = token1;
  }

  if(token1 == addresses.WETH) {
    tokenIn = token1; 
    tokenOut = token0;
  }

  //The quote currency is not WETH
  if(typeof tokenIn === 'undefined') {
    return;
  }

  //We buy for 0.1 ETH of the new token
  const amountIn = ethers.utils.parseUnits('0.01', 'ether');
  const amounts = await router.getAmountsOut(amountIn, [tokenIn, tokenOut]);
  //Our execution price will be a bit different, we need some flexbility
  const amountOutMin = amounts[1].sub(amounts[1].div(10));
  console.log(`
    Buying new token
    =================
    tokenIn: ${amountIn.toString()} ${tokenIn} (WETH)
    tokenOut: ${amountOutMin.toString()} ${tokenOut}
  `);
  const tx = await router.swapExactTokensForTokens(
    amountIn,
    amountOutMin,
    [tokenIn, tokenOut],
    addresses.recipient,
    Date.now() + 1000 * 60 * 10 //10 minutes
  );
  const receipt = await tx.wait(); 
  console.log('Transaction receipt');
  console.log(receipt);
});

I've removed all the code if tried to get it to work
and this is the original error

`New pair detected
=================
token0: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
token1: 0xCa5574f9064E9fA5BFe638466Fe61cD0e265AFd4
pairAddress: 0x7a80dF864Ac54d0bCFf9AF3ee758fFf683Dbd681

Buying new token
=================
tokenIn: 20000000000000000 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 (WETH)
tokenOut: 340267027755796295 0xCa5574f9064E9fA5BFe638466Fe61cD0e265AFd4

(node:11176) UnhandledPromiseRejectionWarning: Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"reason":"cannot estimate gas; transaction may fail or may require manual gas limit","code":"UNPREDICTABLE_GAS_LIMIT","error":{"code":3,"response":"{"jsonrpc":"2.0","id":10,"error":{"code":3,"data":"0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000245472616e7366657248656c7065723a205452414e534645525f46524f4d5f4641494c454400000000000000000000000000000000000000000000000000000000","message":"execution reverted: TransferHelper: TRANSFER_FROM_FAILED"}}"},"method":"estimateGas","transaction":{"from":"0x6657acbCF04775b8D36Ca0659F08F281f635F538","gasPrice":{"type":"BigNumber","hex":"0x10ff239a00"},"to":"0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D","data":"0x38ed173900000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000004b8df0f1629874700000000000000000000000000000000000000000000000000000000000000a00000000000000000000000006657acbcf04775b8d36ca0659f08f281f635f53800000000000000000000000000000000000000000000000000000179705aaf4d0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000ca5574f9064e9fa5bfe638466fe61cd0e265afd4","accessList":null}}, tx={"data":"0x38ed173900000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000004b8df0f1629874700000000000000000000000000000000000000000000000000000000000000a00000000000000000000000006657acbcf04775b8d36ca0659f08f281f635f53800000000000000000000000000000000000000000000000000000179705aaf4d0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000ca5574f9064e9fa5bfe638466fe61cd0e265afd4","to":{},"from":"0x6657acbCF04775b8D36Ca0659F08F281f635F538","gasPrice":{},"nonce":{},"gasLimit":{},"chainId":{}}, code=UNPREDICTABLE_GAS_LIMIT, version=abstract-signer/5.1.0)
at Logger.makeError (C:\Users\TEST MM\Desktop\unibot\node_modules@ethersproject\logger\lib\index.js:180:21)
at Logger.throwError (C:\Users\TEST MM\Desktop\unibot\node_modules@ethersproject\logger\lib\index.js:189:20)
at C:\Users\TEST MM\Desktop\unibot\node_modules@ethersproject\abstract-signer\lib\index.js:263:47
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async Promise.all (index 5)
(node:11176) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)`

Thanks in advance, I appreciate you taking the time.. :)

@ricmoo
Copy link
Member

ricmoo commented May 16, 2021

You still need to pass the overrides (with gasLimit) into the transaction method to const tx = await router.swapExactTokensForTokens(...) that @zemse recommended above.

@williamoc74
Copy link

OK, I've tried what I think you mean(I am a noob here, and I realise this isn't a tutorial type forum for noobs so I do appreciate both of you helping me figure this out :) )
but I'm getting another error. The syntax seems correct but it seems as tho I'm just not putting the code in the correct location and the error is with how the function is called.

This is the changed code
//We buy for 0.1 ETH of the new token const amountIn = ethers.utils.parseUnits('0.01', 'ether'); const amounts = await router.getAmountsOut(amountIn, [tokenIn, tokenOut]); //Our execution price will be a bit different, we need some flexbility const amountOutMin = amounts[1].sub(amounts[1].div(10)); console.log(
Buying new token
=================
tokenIn: ${amountIn.toString()} ${tokenIn} (WETH)
tokenOut: ${amountOutMin.toString()} ${tokenOut}
`);
const tx = await router.swapExactTokensForTokens(
await contract.yourMethod(arg1, arg2, {gasPrice: ethers.utils.parseUnits('100', 'gwei'), gasLimit: 1000000});

amountIn,
amountOutMin,
[tokenIn, tokenOut],
addresses.recipient,
Date.now() + 1000 * 60 * 10 //10 minutes

);
const receipt = await tx.wait();
console.log('Transaction receipt');
console.log(receipt);
});`

and this is a screenshot of the error, the last error I posted looked kind of messy so hopefully a screenshot is better.

Screenshot 2021-05-16 at 11 54 29

Thanks again

@williamoc74
Copy link

Ok so I have a bit of movement on this.
I've set gas limit and price and it's actually trying to buy the token now and it sucks the gas but she doesn't complete the transaction.
I've attached the code and the errors on etherscan.
Screenshot 2021-05-18 at 13 14 16
Screenshot 2021-05-18 at 13 13 36
Screenshot 2021-05-18 at 13 13 32

@williamoc74
Copy link

This is the error log from terminal when it fails..
Screenshot 2021-05-18 at 13 27 28

@zemse
Copy link
Collaborator

zemse commented May 18, 2021

Can you recheck if you have 0.001 WETH balance? Also note it's not ETH balance, it's WETH. If you don't have that, you first have to convert your ETH into WETH using the deposit function on WETH contract.

This is the error log from terminal when it fails..

BTW from next time pls copy and paste the text if possible instead of a screenshot. Since it enables someone to copy some addresses/tx hashes from it and debug for you.

@williamoc74
Copy link

williamoc74 commented May 18, 2021

Ah ok - that makes sense, the code i was copying in previous posts seemed messy so thought screenshots were better.

WETH balance is there ready to go so currently have enough there.. I have ETH in the wallet for gas and WETH for the swap..

@zemse
Copy link
Collaborator

zemse commented May 18, 2021

Oh, then it should work. Can you give me the tx hash? I can try to see.

the code i was copying in previous posts seemed messy

You can give this doc a try, and it will be best if you can include the minimal code required to reproduce the problem / show your use case.

@williamoc74
Copy link

@zemse
Copy link
Collaborator

zemse commented May 18, 2021

Oh I just checked the trace on tenderly, and from that, it appears that there is no WETH approval to the router contract for spending your WETH.

I'd suggest you give the router contract infinite approval (ethers.constants.MaxUint256) for your WETH. It will save you from doing multiple approves for each swaps

@zemse
Copy link
Collaborator

zemse commented May 18, 2021

The error on etherscan is just out of gas error. Also gasLimit: '50000', is not enough for a uniswap swap. You need about 120,000 or so. But try passing in higher gasLimit like 200,000.

@williamoc74
Copy link

Okay, I will try that and update :)

@williamoc74
Copy link

Worked like a charm :)
https://etherscan.io/tx/0x52ac76c29519ba4da3c3398289501194e42bb20459a87f919483dc157a7c3e55
Send me your Eth address because i want to send you a tip! Thanks a lot :)

@zemse
Copy link
Collaborator

zemse commented May 18, 2021

Thanks! My address is zemse.eth (0xf51C53b2C184Aa43A7d24aA4f0Cf13D0e8b56c51)

@williamoc74
Copy link

Tip Sent :)

@williamoc74
Copy link

Yo :) Im back again!
So ive been testing this the past few hours with test funds! Ive come across a token that was purchased that gave this error when I try to swap back to WETH, more than likely a scam(definitely a scam) but im just wondering what is the reason it cant be swapped back to WETH..Ive paid a lot of university fees today, Gas included haha!
WhatsApp Image 2021-05-18 at 21 50 19
Thanks :)

@George8812
Copy link

George8812 commented May 18, 2021

Ok so I have a bit of movement on this.
I've set gas limit and price and it's actually trying to buy the token now and it sucks the gas but she doesn't complete the transaction.
I've attached the code and the errors on etherscan.
Screenshot 2021-05-18 at 13 14 16
Screenshot 2021-05-18 at 13 13 36
Screenshot 2021-05-18 at 13 13 32

Hi!

I have the same problem, same code like you, for buying new pairs. What lines have you added?
I have this one but doesnt work.

const tx = await router.swapExactTokensForTokens(
amountIn,
amountOutMin,
[tokenIn, tokenOut],
addresses.recipient,
Date.now() + 1000 * 60 * 10,
{
gasLimit: '200000'
gasPrice: '15000000000'
}

@williamoc74
Copy link

Hey George! When you say it doesn't work, what do you mean? Is it giving an error?
Ricmoo & Zemse will no doubt help you out!

@George8812
Copy link

This is the code for bsc. It find new pairs, approves wbnb but doesnt buy the token.

const ethers = require('ethers');

const addresses = {
WBNB: '0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c',
factory: '0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73',
router: '0x10ED43C718714eb63d5aA57B78B54704E256024E',
recipient: 'wallet'

}

//First address of this mnemonic must have enough BNB to pay for tx fess
const mnemonic = '---';

const provider = new ethers.providers.WebSocketProvider('wss adress');
const wallet = ethers.Wallet.fromMnemonic(mnemonic);
const account = wallet.connect(provider);
const factory = new ethers.Contract(
addresses.factory,
['event PairCreated(address indexed token0, address indexed token1, address pair, uint)'],
account
);
const router = new ethers.Contract(
addresses.router,
[
'function getAmountsOut(uint amountIn, address[] memory path) public view returns (uint[] memory amounts)',
'function swapExactTokensForTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts)'
],
account
);

const wbnb = new ethers.Contract(
addresses.WBNB,
[
'function approve(address spender, uint amount) public returns(bool)',
],
account
);

const init = async () => {
const tx = await wbnb.approve(
router.address,
'1'
);
const receipt = await tx.wait();
console.log('Transaction receipt');
console.log(receipt);
}

factory.on('PairCreated', async (token0, token1, pairAddress) => {
console.log(New pair detected ================= token0: ${token0} token1: ${token1} pairAddress: ${pairAddress});

//The quote currency needs to be WBNB (we will pay with WBNB)
let tokenIn, tokenOut;
if(token0 === addresses.WBNB) {
tokenIn = token0;
tokenOut = token1;
}

if(token1 == addresses.WBNB) {
tokenIn = token1;
tokenOut = token0;
}

//The quote currency is not WBNB
if(typeof tokenIn === 'undefined') {
return;
}

//We buy for 0.1 BNB of the new token
//ethers was originally created for Ethereum, both also work for BSC
//'ether' === 'bnb' on BSC
const amountIn = ethers.utils.parseUnits('0.01', 'ether');
const amounts = await router.getAmountsOut(amountIn, [tokenIn, tokenOut]);
//Our execution price will be a bit different, we need some flexbility
const amountOutMin = amounts[1].sub(amounts[1].div(10));
console.log(Buying new token ================= tokenIn: ${amountIn.toString()} ${tokenIn} (WBNB) tokenOut: ${amounOutMin.toString()} ${tokenOut});

const tx = await router.swapExactTokensForTokens(
amountIn,
amountOutMin,
[tokenIn, tokenOut],
addresses.recipient,
Date.now() + 1000 * 60 * 10,
{
gasLimit: '100000',
gasPrice: '15000000000'
}

);
const receipt = await tx.wait();
console.log('Transaction receipt');
console.log(receipt);
});

init();

@davvvvvvvy
Copy link

Same problem here with BSC. How to setup gasprice and gaslimit?

@isaac0310
Copy link

This is the code for bsc. It find new pairs, approves wbnb but doesnt buy the token.

const ethers = require('ethers');

const addresses = {
WBNB: '0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c',
factory: '0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73',
router: '0x10ED43C718714eb63d5aA57B78B54704E256024E',
recipient: 'wallet'

}

//First address of this mnemonic must have enough BNB to pay for tx fess
const mnemonic = '---';

const provider = new ethers.providers.WebSocketProvider('wss adress');
const wallet = ethers.Wallet.fromMnemonic(mnemonic);
const account = wallet.connect(provider);
const factory = new ethers.Contract(
addresses.factory,
['event PairCreated(address indexed token0, address indexed token1, address pair, uint)'],
account
);
const router = new ethers.Contract(
addresses.router,
[
'function getAmountsOut(uint amountIn, address[] memory path) public view returns (uint[] memory amounts)',
'function swapExactTokensForTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts)'
],
account
);

const wbnb = new ethers.Contract(
addresses.WBNB,
[
'function approve(address spender, uint amount) public returns(bool)',
],
account
);

const init = async () => {
const tx = await wbnb.approve(
router.address,
'1'
);
const receipt = await tx.wait();
console.log('Transaction receipt');
console.log(receipt);
}

factory.on('PairCreated', async (token0, token1, pairAddress) => {
console.log(New pair detected ================= token0: ${token0} token1: ${token1} pairAddress: ${pairAddress});

//The quote currency needs to be WBNB (we will pay with WBNB)
let tokenIn, tokenOut;
if(token0 === addresses.WBNB) {
tokenIn = token0;
tokenOut = token1;
}

if(token1 == addresses.WBNB) {
tokenIn = token1;
tokenOut = token0;
}

//The quote currency is not WBNB
if(typeof tokenIn === 'undefined') {
return;
}

//We buy for 0.1 BNB of the new token
//ethers was originally created for Ethereum, both also work for BSC
//'ether' === 'bnb' on BSC
const amountIn = ethers.utils.parseUnits('0.01', 'ether');
const amounts = await router.getAmountsOut(amountIn, [tokenIn, tokenOut]);
//Our execution price will be a bit different, we need some flexbility
const amountOutMin = amounts[1].sub(amounts[1].div(10));
console.log(Buying new token ================= tokenIn: ${amountIn.toString()} ${tokenIn} (WBNB) tokenOut: ${amounOutMin.toString()} ${tokenOut});

const tx = await router.swapExactTokensForTokens(
amountIn,
amountOutMin,
[tokenIn, tokenOut],
addresses.recipient,
Date.now() + 1000 * 60 * 10,
{
gasLimit: '100000',
gasPrice: '15000000000'
}

);
const receipt = await tx.wait();
console.log('Transaction receipt');
console.log(receipt);
});

init();

Same issue. I run the code, It does not buy tokens.

@zemse
Copy link
Collaborator

zemse commented May 20, 2021

Same problem here with BSC. How to setup gasprice and gaslimit?

Hey @ivekivek, you can refer to #40 (comment) above. Lmk if that doesn't help

@George8812 @isaac0310 Can you try the above discussed solutions? Just to summarise:

@originbond
Copy link

Worked like a charm :)
https://etherscan.io/tx/0x52ac76c29519ba4da3c3398289501194e42bb20459a87f919483dc157a7c3e55
Send me your Eth address because i want to send you a tip! Thanks a lot :)

I wanted to try out this bot as well. What should I do about the selling part, should I automate it, and do it immediately after the buy, or wait and then sell ? How many seconds should I wait before the sell ?

@carlomallone
Copy link

carlomallone commented May 22, 2021

Hey mates! Thanks for your work. I'm trying to make this work for BSC with no luck. I followed @zemse advice and still got errors.

My code:

const ethers = require('ethers')

const addresses = {
  WBNB: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c',
  factory: '0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73',
  router: '0x10ED43C718714eb63d5aA57B78B54704E256024E',
  recipient: '...'
}

const mnemonic = '....'
const pk = '...'

const ws = "wss://bsc-ws-node.nariox.org:443"
const provider = new ethers.providers.WebSocketProvider(ws)

const wallet = new ethers.Wallet(pk)
const account = wallet.connect(provider)
const factory = new ethers.Contract(
  addresses.factory,
  ['event PairCreated(address indexed token0, address indexed token1, address pair, uint)'],
  account
)
const router = new ethers.Contract(
  addresses.router,
  [
    'function getAmountsOut(uint amountIn, address[] memory path) public view returns (uint[] memory amounts)',
    'function swapExactTokensForTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts)',
    'function swapExactETHForTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts)'
  ],
  account
)

const wbnb = new ethers.Contract(
  addresses.WBNB,
  [
    'function approve(address spender, uint amount) public returns(bool)'
  ],
  account
)

const sniper = async () => {
  const tx = await wbnb.approve(
    router.address,
    ethers.constants.MaxUint256
  )
  const receipt = await tx.wait()
  console.log('Transaction receipt')
  console.log(receipt)
}

const buy = async (token0: any, token1: any) => {
  // The quote currency needs to be WBNB (we will pay with WBNB)
  let tokenIn, tokenOut
  if(token0 === addresses.WBNB) {
    tokenIn = token0
    tokenOut = token1
  }

  if(token1 == addresses.WBNB) {
    tokenIn = token1
    tokenOut = token0
  }

  // The quote currency is not WBNB
  if(typeof tokenIn === 'undefined') {
    return
  }

  // We buy for 0.002 BNB of the new token
  const amountIn = ethers.utils.parseUnits('0.002', 'ether')
  const amounts = await router.getAmountsOut(amountIn, [tokenIn, tokenOut])
  // Our execution price will be a bit different, we need some flexbility
  const amountOutMin = amounts[1].sub(amounts[1].div(10))
  console.log(`
    Buying new token
    =================
    tokenIn: ${amountIn.toString()} ${tokenIn} (WBNB)
    tokenOut: ${amountOutMin.toString()} ${tokenOut}
  `)
  const tx = await router.swapExactTokensForTokens(
    amountIn,
    amountOutMin,
    [tokenIn, tokenOut],
    addresses.recipient,
    Math.floor(Date.now() / 1000) + 60 * 10, // 10 minutes from the current Unix time
    { gasPrice: 5000000000, gasLimit: 1000000 }
  )
  const receipt = await tx.wait()
  console.log('Transaction receipt')
  console.log(receipt)
}

factory.on('PairCreated', async (token0: any, token1: any, pairAddress: any) => {
  console.log(`
    New pair detected
    =================
    token0: ${token0}
    token1: ${token1}
    pairAddress: ${pairAddress}
  `)

  setTimeout(async() => {
    await buy(token0, token1)
  }, 15000)
})

Error:
Error: transaction failed (transactionHash="0x3db984ba2f4161ff8ca52cb552070969583dec93438ed1e87037ae3b8358026f", transaction={"nonce":113,"gasPrice":{"type":"BigNumber","hex":"0x012a05f200"},"gasLimit":{"type":"BigNumber","hex":"0x0f4240"},"to":"0x10ED43C718714eb63d5aA57B78B54704E256024E","value":{"type":"BigNumber","hex":"0x00"},"data":"0x38ed173900000000000000000000000000000000000000000000000000071afd498d0000000000000000000000000000000000000000000000000001523b40d52210e90a00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000d8b44b65905193f2770fc3c4ec35323639f5f7c10000000000000000000000000000000000000000000000000000000060a858c00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000bb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c000000000000000000000000ec1e88465843e2a6e4d79c28e55f9d71640bf248","chainId":56,"v":148,"r":"0x143c5bd3abafd872b94e52ae4a7de768d1ce25f5f7b5474a5450827ff560bd20","s":"0x013227a41112cc3bd09d3123f3e5cc314a02f13d38b7202200d6e2d08e7e92e6","from":"0xD8B44B65905193F2770Fc3C4ec35323639F5F7c1","hash":"0x3db984ba2f4161ff8ca52cb552070969583dec93438ed1e87037ae3b8358026f","type":null}, receipt={"to":"0x10ED43C718714eb63d5aA57B78B54704E256024E","from":"0xD8B44B65905193F2770Fc3C4ec35323639F5F7c1","contractAddress":null,"transactionIndex":151,"gasUsed":{"type":"BigNumber","hex":"0x888f"},"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","blockHash":"0xa1f5b5b47c577605b7c6526099feaae82a723cc84349754d338411809ffa5158","transactionHash":"0x3db984ba2f4161ff8ca52cb552070969583dec93438ed1e87037ae3b8358026f","logs":[],"blockNumber":7616433,"confirmations":1,"cumulativeGasUsed":{"type":"BigNumber","hex":"0xce198e"},"status":0,"byzantium":true}, code=CALL_EXCEPTION, version=providers/5.2.0)

Thanks for your help!

@zemse
Copy link
Collaborator

zemse commented May 22, 2021

Hey guys, if you have a faling transaction, I'd recommend you to check it once on tenderly. It helps you see reason of your transaction failure.

In case of @shelkem, you do not have enough WBNB token balance.

https://dashboard.tenderly.co/tx/bsc/0x3db984ba2f4161ff8ca52cb552070969583dec93438ed1e87037ae3b8358026f

@originbond
Copy link

@williamoc74
I wanted to try out this bot as well. What should I do about the selling part, should I automate it, and do it immediately after the buy, or wait and then sell ? How many seconds should I wait before the sell ?

@George8812
Copy link

const pk = '...'

What have you enter here?
const pk = ' '

@williamoc74
Copy link

@williamoc74
I wanted to try out this bot as well. What should I do about the selling part, should I automate it, and do it immediately after the buy, or wait and then sell ? How many seconds should I wait before the sell ?

The selling is tricky. To be honest, the bot isn't worth it the way it is, you just end up picking up all the garbage and getting rugged constantly..

I'm trying to get it to run on pancake, I have it detecting them and trying to buy but but it doesn't go through with the transaction.

It executes upto this point
const tx = await router.swapExactTokensForTokens( amountIn, amountOutMin, [tokenIn, tokenOut], addresses.recipient, Date.now() + 1000 * 60 * 10, //10 minutes { 'gasLimit': 345684, 'gasPrice': ethers.utils.parseUnits( '15', 'gwei'), } );

but doesn't buy - @ricmoo @zemse any ideas? I'm sure it's something simple, it's wrecking me head..

I've tried using 'swapExactETHTokensForTokens' too and still no joy..

@originbond
Copy link

@williamoc74
I wanted to try out this bot as well. What should I do about the selling part, should I automate it, and do it immediately after the buy, or wait and then sell ? How many seconds should I wait before the sell ?

The selling is tricky. To be honest, the bot isn't worth it the way it is, you just end up picking up all the garbage and getting rugged constantly..

I'm trying to get it to run on pancake, I have it detecting them and trying to buy but but it doesn't go through with the transaction.

It executes upto this point
const tx = await router.swapExactTokensForTokens( amountIn, amountOutMin, [tokenIn, tokenOut], addresses.recipient, Date.now() + 1000 * 60 * 10, //10 minutes { 'gasLimit': 345684, 'gasPrice': ethers.utils.parseUnits( '15', 'gwei'), } );

but doesn't buy - @ricmoo @zemse any ideas? I'm sure it's something simple, it's wrecking me head..

I've tried using 'swapExactETHTokensForTokens' too and still no joy..

I may be able to give you a hand with debugging.
Please message me on telegram : @Origin_Bond

@zemse
Copy link
Collaborator

zemse commented May 24, 2021

@williamoc74 Can you console.log(tx.hash) and share the hash or do you get an error?

@juloxrox
Copy link

Hi everyone,

Previous answers helped a lot but I'm still facing a last one https://dashboard.tenderly.co/tx/bsc/0x50e1f5ac4f1c89efd422814876c7b0a098c25868bc6f94a26446815fd4de9f0b
and I don't figure out the reasons whereas my balances look okay: 0.786 BNB and 1.397 WBNB.

Here are my gas limits settings { gasPrice: 5000000000, gasLimit: 1000000 } and here is the error message:
reason: 'transaction failed',
code: 'CALL_EXCEPTION',

Can someone help please?
Thanks in advance!

@zemse
Copy link
Collaborator

zemse commented May 24, 2021

@juloxrox In the tenderly it shows that your tx was failed because there wasn't enough allowance.

I wish to see the day when errors in the blockchain ecosystem would become as great as errors spit out by the Rust compiler.

@juloxrox
Copy link

juloxrox commented May 24, 2021

@juloxrox In the tenderly it shows that your tx was failed because there wasn't enough allowance.

I wish to see the day when errors in the blockchain ecosystem would become as great as errors spit out by the Rust compiler.

@zemse Yes this is what I get but I'm wondering why? It's on the contract side right? What does it mean there is no allowance? And what can I do to avoid that?

In my approvel function, my allowance for WBNB is set to ethers.constants.MaxUint256

@williamoc74
Copy link

What code are you using to execute the transaction here @juloxrox
'const amounts=await router.getAmountsOut(amountIn,[tokenIn,tokenOut]);
const tx = await router.swapExactTokensForTokens(
amountIn,
amountOutMin,
[tokenIn, tokenOut],
addresses.recipient,
Date.now() + 1000 * 60 * 10 //10 minutes
);

{
gasLimit: '40000'
gasPrice: '5000000000'
}'

@juloxrox
Copy link

@williamoc74 I'm swappping WBNB for now with those gas settings { gasPrice: 5000000000, gasLimit: 1000000 }
I also put that in the approval function as the amount: ethers.constants.MaxUint256

@carlomallone
Copy link

const pk = '...'

What have you enter here?
const pk = ' '

My wallet private key @George8812

@AndreaBarbon
Copy link

@williamoc74
I wanted to try out this bot as well. What should I do about the selling part, should I automate it, and do it immediately after the buy, or wait and then sell ? How many seconds should I wait before the sell ?

Eh eh eh, that's up to you :p

@originbond
Copy link

@williamoc74
I wanted to try out this bot as well. What should I do about the selling part, should I automate it, and do it immediately after the buy, or wait and then sell ? How many seconds should I wait before the sell ?

Eh eh eh, that's up to you :p

Thank you Dr Evil : ¬ ) Just seeing if anyone had any tips, but I guess I'll try a few experiments.....

@AndreaBarbon
Copy link

Be creative! Mu suggestion is to gather some data and make some simulations.
But be ware! Sometimes you'll find scam token that you can buy but not sell

@Trickle-dev
Copy link

@zemse thanks for your answers in this thread. Has been helpful.

I am getting started with ethers.js and was hoping you could point me in the right direction for working the approve function in.

I am honestly not sure where to start here.

Basically I am sending the tx but receiving allowance error

require(allowance[src][msg.sender] >= wad);

I have tried re-working some of the approve functions used here for wbnb but to no avail. Such as:

const weth = new ethers.Contract(
addresses.WETH,
[
'function approve(address spender, uint amount) public returns(bool)',
],
account
);

const init = async () => {
const tx = await weth.approve(
router.address,
'1'
);
const receipt = await tx.wait();
console.log('Transaction receipt');
console.log(receipt);
}

Using this I end up with an error for:

TypeError: tx.wait is not a function

I can see the function in ERC20 contracts, for the life of me I just can not find similar scripts or guides to draw from. Any help would be appreciated.

@williamoc74 if you could share your approve function that would be amazing

@Trickle-dev
Copy link

Update to this I think I have it working, or at least I can see txhash is now approving 4 eth.
addresses.WETH is defined in:

const addresses = {
WETH

const gasPrice = ethers.utils.parseUnits('100', 'gwei');
const gasLimit = 250000


const weth = new ethers.Contract(
  addresses.WETH,
  [
      'function approve(address spender, uint amount) public returns(bool)',
  ],
  account
);


const valueToApprove = ethers.utils.parseUnits('4', 'ether');

console.log('Ready to approve');

const init = async () => {
  const tx = await weth.approve(
      router.address,
      valueToApprove,
      { gasPrice: gasPrice, gasLimit: gasLimit }
  );

  console.log('After Approve');
        const receipt = await tx.wait();
        console.log('Transaction receipt');
        console.log(receipt);
}

ademidun added a commit to atilatech/arthouse-api that referenced this issue Jun 18, 2022
Polygon increased it's minimum gas price from 30 Gwei to 1Gwei to curb spam.

Other blockchains might change their default gas price as well so we should get that value from the provider.

see: https://medium.com/stakingbits/polygon-minimum-gas-fee-is-now-30-gwei-to-curb-spam-8bd4313c83a2

ethers-io/ethers.js#2828 (comment)

ethers-io/ethers.js#40 (comment)
@hyndsite
Copy link

hyndsite commented Jun 22, 2022

@ricmoo or someone - why would I need to provide gas price or gas limit overrides for an external/view contract function if they don't require gas and are not being performed inside another transaction? And, no other processing is occurring but returning contract state variables.

function getDetails()
external
view
returns (
uint256,
uint256,
uint256,
address,
uint256
)

I encountered the "cannot estimate gas; transaction may fail or may require manual gas limit" error originally. It also required that I use a signer and not just a provider when creating the contract instance.

To make it worse, once I switched to a signer, and provided those overrides

const overrides = {
            gasPrice: ethers.utils.parseUnits("50000000000", "wei"),
            gasLimit: ethers.utils.parseUnits("100000000000", "wei")
};

const response = await contract.getDetails(overrides);

I receive an insufficient funds error (Rinkeby) when I have .6 ETH on the account:

Error: insufficient funds for intrinsic transaction cost [ See: https://links.ethers.org/v5-errors-INSUFFICIENT_FUNDS ] (error={"code":-32000,"message":"err: insufficient funds for gas * price + value: address 0xc0Eb169794B18685a67C0a998292D184Ddeaeba3 have 600000000000000000 want 200000000000000000000000 (supplied gas 500000000)"}, method="call", transaction={"from":"0xc0Eb169794B18685a67C0a998292D184Ddeaeba3","gasLimit":{"type":"BigNumber","hex":"0x058d15e176280000"},"gasPrice":{"type":"BigNumber","hex":"0x016bcc41e90000"},"to":"0x5FbDB2315678afecb367f032d93F642f64180aa3","data":"0x936afab3","accessList":null}, code=INSUFFICIENT_FUNDS, version=providers/5.4.5)

@Ej-leone
Copy link

Ej-leone commented Dec 1, 2022

@ricmoo or someone - why would I need to provide gas price or gas limit overrides for an external/view contract function if they don't require gas and are not being performed inside another transaction? And, no other processing is occurring but returning contract state variables.

function getDetails() external view returns ( uint256, uint256, uint256, address, uint256 )

I encountered the "cannot estimate gas; transaction may fail or may require manual gas limit" error originally. It also required that I use a signer and not just a provider when creating the contract instance.

To make it worse, once I switched to a signer, and provided those overrides

const overrides = {
            gasPrice: ethers.utils.parseUnits("50000000000", "wei"),
            gasLimit: ethers.utils.parseUnits("100000000000", "wei")
};

const response = await contract.getDetails(overrides);

I receive an insufficient funds error (Rinkeby) when I have .6 ETH on the account:

Error: insufficient funds for intrinsic transaction cost [ See: https://links.ethers.org/v5-errors-INSUFFICIENT_FUNDS ] (error={"code":-32000,"message":"err: insufficient funds for gas * price + value: address 0xc0Eb169794B18685a67C0a998292D184Ddeaeba3 have 600000000000000000 want 200000000000000000000000 (supplied gas 500000000)"}, method="call", transaction={"from":"0xc0Eb169794B18685a67C0a998292D184Ddeaeba3","gasLimit":{"type":"BigNumber","hex":"0x058d15e176280000"},"gasPrice":{"type":"BigNumber","hex":"0x016bcc41e90000"},"to":"0x5FbDB2315678afecb367f032d93F642f64180aa3","data":"0x936afab3","accessList":null}, code=INSUFFICIENT_FUNDS, version=providers/5.4.5)

@hyndsite were you able to sort this out facing a similar issue ?

@ricmoo
Copy link
Member

ricmoo commented Dec 1, 2022

A pure or view function (external/public are irrelevant to ethers ABI) do not require gas limit and won’t look it up. Usually this error is caused by forgetting the pure or view keyword in the abi…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Documentation related issue.
Projects
None yet
Development

No branches or pull requests