Closed subramanianv closed 6 years ago
We originally did this, but there were times the estimated gas was incorrect and would cause transactions to fail.
Perhaps we should revisit this. The gas estimation in the nodes may have improved.
In several of my apps, I also check for code at the target address and if there is none, use 21000
. The updates I'm making will allow any transaction request property to be a promise (right now most of them can be, but not gas limit). Once that is done, it will be quiet easy to add this.
This is now the default in the TypeScript branch.
Hi, how can I change the default gas limit, my deployment is failing with gas limit errors and I couldn't find any way to change. Not I am deploying to local ganache env and incrased the gas limit etc there also, still couldn't get to deploy with etherjs Thanks a lot Sohel
Are you using the version from npm, it the v4 TypeScript branch?
For npm v3, you should be able to set Wallet.defaultGasLimit or pass in overrides to a contract call by passing 1 extra parameter to the call.
That worked!....(I am using 3.0.25 from npm)
Kudos to ethers.js team, excellent support.
Thanks a lot, sohel@openapp.ca
Awesome! In v4, the estimate will be used. I'll close this, but if you have any further issues, please feel free to re-open. :)
btw @ricmoo in using v4.0.0-beta.6 our tests on ganache are failing when they use eth_estimateGas — we're getting too small of a gas suggestion and getting out of gas error. When I specify the gas limit manually on the transaction, the tests pass. I can't tell if this is a problem with ganache or ethers at the moment. If you try to run yarn test
for https://github.com/horizon-games/arcadeum/tree/master/examples/ttt you'll see what I mean.
I am using https://cdn.ethers.io/scripts/ethers-v3.min.js
Getting following error: ethers-v3.min.js:5 Uncaught (in promise) Error: insufficient funds for gas * price + value at e (ethers-v3.min.js:5) at XMLHttpRequest.g.onreadystatechange (ethers-v3.min.js:6) e @ ethers-v3.min.js:5 g.onreadystatechange @ ethers-v3.min.js:6 Promise.then (async) (anonymous) @ test.html:129
How to calculate gasprice automatically in ethers-v3.min.js.
To compute the gas in v3, you can use:
var tx = {
to: toAddress,
data: data,
value: value
};
provider.estimateGas(tx).then(function(estimate) {
tx.gasLimit = estimate;
});
Obviously, it's much easier in v4. :)
Yes i have received the gas value.. 21000
but how to calculate this while transferring funds from one to other account:
Please see my code:
var transaction = { from: "0xca6d44FEeE1B1E9F2f727e3C905C25Fa37E4927E", to: "0xB4e8AC80CbDc013F8Fc249F422bAB126e45d6D61", value: utils.parseEther("0.0034802"), data: "0x",
//chainId: providers.networks.homestead.chainId
};
var provider = providers.getDefaultProvider();
provider.estimateGas(transaction).then(function(estimate) { transaction.gasLimit = estimate; console.log('estimate: ' + estimate);
});
var signedTransaction = wallet.sign(transaction); console.log(signedTransaction);
provider.sendTransaction(signedTransaction).then(function(hash) { console.log('Hash: ' + hash); // Hash: });
Oh, you must put the send transaction call inside the promise for the gas estimate. You are sending the transaction before the gasLimit is correctly set. Make sense?
I’m on my phone now, but if it doesn’t make sense, I can type it easier once I’m at my computer.
Please try to write a code when you are on your computer.
Please. it will help me a lot.
Can you try this?
` var provider = providers.getDefaultProvider();
provider.estimateGas(transaction).then(function (estimate) { transaction.gasLimit = estimate; console.log('estimate: ' + estimate);
var signedTransaction = wallet.sign(transaction);
console.log(signedTransaction);
provider.sendTransaction(signedTransaction).then(function (hash) {
console.log('Hash: ' + hash);
// Hash:
});
});
`
Same error:
Consol:
Address: 0xB4e8AC80CbDc013F8Fc249F422bAB126e45d6D61 test.html:135 estimate: 21000 test.html:138 0xf869808504a817c80082520894b4e8ac80cbdc013f8fc249f422bab126e45d6d61852e90edd000801ca0851024a704a866a01ecc41d81e14476ba314c7407375f27c9b98688e302ce5c3a04da2536f8785b5109c5eb14f2c4150076549d39037eef55900ca010f5bb684b8 ethers-v3.min.js:5 Uncaught (in promise) Error: insufficient funds for gas * price + value at e (ethers-v3.min.js:5) at XMLHttpRequest.g.onreadystatechange (ethers-v3.min.js:6) e @ ethers-v3.min.js:5 g.onreadystatechange @ ethers-v3.min.js:6 Promise.then (async) (anonymous) @ test.html:140 Promise.then (async) (anonymous) @ test.html:133
Code:
var transaction = { // Recommendation: omit nonce; the provider will query the network nonce: 0, // Gas Limit; 21000 will send ether to another use, but to execute contracts // larger limits are required. The provider.estimateGas can be used for this. gasLimit: 1000000, // Recommendations: omit gasPrice; the provider will query the network gasPrice: utils.bigNumberify("20000000000"), // Required; unless deploying a contract (in which case omit) from: "0xca6d44FEeE1B1E9F2f727e3C905C25Fa37E4927E", to: "0xB4e8AC80CbDc013F8Fc249F422bAB126e45d6D61", // Optional //data: "0x", // Optional value: ethers.utils.parseEther("0.0000002"), // Recommendation: omit chainId; the provider will populate this // chaindId: providers.networks.homestead.chainId };
var provider = providers.getDefaultProvider();
provider.estimateGas(transaction).then(function (estimate) { transaction.gasLimit = estimate; console.log('estimate: ' + estimate);
var signedTransaction = wallet.sign(transaction); console.log(signedTransaction);
provider.sendTransaction(signedTransaction).then(function (hash) { console.log('Hash: ' + hash); // Hash: }); });
I'm using ethers 4.0.7 with MetaMask as a Web3Provider. My contracts are on Ropsten.
This transaction fails with out of gas!
errors:
const gasLimit = await state.chainInfo.data.provider.estimateGas(setOrganisation)
const tx = await orgContract.setOrganisation(org, {gasLimit: gasLimit})
However, I can make it work with a magic number:
let gasLimit = await state.chainInfo.data.provider.estimateGas(setOrganisation)
gasLimit *= 4
const tx = await orgContract.setOrganisation(org, {gasLimit: gasLimit})
The estimate was 56000, but the actual gas used was 172000. Why is estimateGas so wildly innaccurate? Am I doing something wrong?
Can you post the contract function code?
Unfortunately the gas estimation in Ethereum nodes is sometimes wildly inaccurate, especially if it calls to external contracts.
We added “gas” as a property to the ABI, so you can specify per function what gasLimit it should use (skipping estimates entirely). If you use human-readable ABI, as add a “@172000” to the end of the signature string. :)
Can you post the contract function code?
Mostly (I can post the relevant parts of the interface and strings library later, if you wish). Anyway, below:
pragma solidity ^0.5.0;
pragma experimental ABIEncoderV2;
import "./Organisations.sol";
import "./Strings.sol";
contract IATIOrganisations is Organisations {
bytes32[] orgReferences;
mapping(bytes32 => Organisation) private organisations;
event SetOrganisation(bytes32 _orgRef, Organisation _org);
function setOrganisation(Organisation memory _org) public {
require (_org.orgRef[0] != 0 && bytes(_org.name).length > 0 && bytes(_org.identifier).length > 0);
organisations[_org.orgRef].orgRef = _org.orgRef;
organisations[_org.orgRef].name = _org.name;
organisations[_org.orgRef].identifier = _org.identifier;
if(!getOrganisationExists(_org.orgRef)) {
orgReferences.push(_org.orgRef);
}
emit SetOrganisation(_org.orgRef, _org);
}
add a “@172000
Ooo, nice! So something like this?
"function setOrganisation(tuple(bytes32 orgRef, string name, string identifier) _org)@172000"
Actually, that setOrganisation
Solidity function, above, uses ~125000 gas, not 172000.
And just a note to others - the "function foo()@123000"
syntax will add 21000 to the amount specified, so for the foo
function, I'd be setting a gasLimit of 144000.
Oh yes! Sorry, I forgot the mention the transaction base cost is excluded.
I also meant to mention if you write your contacts in Vyper, the gas is already included in the ABI it outputs (with the same excluding base cost caveat), since all vyper calls have a known upper bound cost.
The main advantage of excluding the base cost is that multi-sig on-chain wallets can add their marginal overhead themselves, or in the case of atomic semantics on a series of transactions to be executed at once, an appropriate gas limit can be estimated.
This will all make more sense once I get around to writing a Medium article. :)
Thanks @ricmoo :)
...the reasons for looking harder at Vyper are beginning to mount...
To compute the gas in v3, you can use:
var tx = { to: toAddress, data: data, value: value }; provider.estimateGas(tx).then(function(estimate) { tx.gasLimit = estimate; });
Obviously, it's much easier in v4. :)
but how to compute gas in v4, i got a error gas required exceed allowance, i am using v "ethers": "^4.0.20",
thanks a lot
The gas limit should be set for you automatically, by calling the estimateGas
, however, in certain situations the Ethereum network seems less-than-perfect at estimating the cost. In these cases, you may need to hard-code an expected gas limit.
Can you include your code?
The gas limit should be set for you automatically, by calling the
estimateGas
, however, in certain situations the Ethereum network seems less-than-perfect at estimating the cost. In these cases, you may need to hard-code an expected gas limit.Can you include your code?
referWithdraw(wallet, v1) { var _this = this; wallet.defaultGasLimit=5000000 let contract = this.global.m3gameContract.connect(wallet); // toast(ethers.utils.parseEther(v1+'')) contract .referWithdraw(ethers.utils.parseEther(v1 + "")) .then(function(tx) { console.log(tx); _this.$q.loading.hide(); }); },
i set it 5000000 still doesn't work ,have any suggestion. the same code worked fine yesterday , but reprot a error failed now
add relative code:
this.global.defaultProvider = ethers.getDefaultProvider( this.global.ethersNet ); let mnemonicWallet = ethers.Wallet.fromMnemonic(plaintext); let wallet = mnemonicWallet.connect(this.global.defaultProvider);
In v4
there is no longer a defaultGasPrice
property on Wallet instances. You will probably want something more like:
let overrides = {
// 500k gas
gasLimit: 500000
};
contract.referWithdraw(wei, overrides).then((tx) => {
console.log(tx);
});
It also looks like you are using v1 + ""
to convert a floating point number to a string, this isn't safe, unfortunately. You should aim to have the number input as a string, and keep it as a string. If the user types "1.0" into an input field, it is already a string, so you can just keep it that way. Once you use parseFloat you may have already discarded part of the value:
console.log("" + parseFloat(1.0000000000000001));
// '1'
ok, i will try it ,thank you for reminding
In
v4
there is no longer adefaultGasPrice
property on Wallet instances. You will probably want something more like:let overrides = { // 500k gas gasLimit: 500000 }; contract.referWithdraw(wei, overrides).then((tx) => { console.log(tx); });
It also looks like you are using
v1 + ""
to convert a floating point number to a string, this isn't safe, unfortunately. You should aim to have the number input as a string, and keep it as a string. If the user types "1.0" into an input field, it is already a string, so you can just keep it that way. Once you use parseFloat you may have already discarded part of the value:console.log("" + parseFloat(1.0000000000000001)); // '1'
I still have problems in gasLimit , @ricmoo can you have some good suggestion ,tanks a lot!
1) when i don't overrides gasLimit ,there is the error ( 2) after I overrides gasLimit:210000 , there is no error above, but when I query the execution result on the etherscan,io ,it failed, like below: 3) after i overrides gasLimit:300000, Calling a contract often goes wrong,The probability of error is greater than set gasLimit:210000
It looks like your function may be throwing (i.e. a failed require) or is very expensive to run...
If you use a tool like remix, it help identify the expected cost to execute the function.
but sometimes the same function and same data , i set gasLimit:210000 , it execute success; and set gasLimit:300000 , if failed . i cann't understand why
It depends on what the function is doing. If it uses the length of a storage variable (which changes with each call), for example, or depends on the block hash, or timestamp it could require different amounts of gas. For example, it is more expensive to set a zero-value storage value to non-zero, than it is to set a non-zero storage value to another non-zero storage value.
The first time an account receives an ERC-20 token is likely going to be more expensive than the second time, for example.
It really comes down to what the code is doing. What you will want to do is find a value that works for the worst case, and use that.
Also, when you specify 210k and it uses all 210k, that means it failed short, so it required more gas, so it may be using the same amount of gas, but just didn't have enough.
Make sense? Please feel free to post code. :)
Does it always works with gasLimit 300k?
it always failed with 300k,
When it fails with 300k, does it consume all 300k gas in the receipt? Or just part of it?
sorry ,maybe i mistake something ,let me check it first!
I see that default the gas limit is 1500000. We should estimate gas for a transaction by default.