Replies: 11 comments 23 replies
-
This seems to happen when deploying through hardhat as well |
Beta Was this translation helpful? Give feedback.
-
I'll look into this. Are you using local hardhat network node as well? Or what is the provider? |
Beta Was this translation helpful? Give feedback.
-
I'm seeing this as well, calling The contract typically rejects with a message like: |
Beta Was this translation helpful? Give feedback.
-
You can see this by adding
|
Beta Was this translation helpful? Give feedback.
-
For more context, I actually want to handle the case where the token doesn't exist, but the expected error is getting masked. async function getOwner(id) {
try {
console.log("fetching owner of token #", id);
const owner = await nftContract.ownerOf(id, { gasLimit: 50000 });
console.log(" owner is:", owner);
} catch (err) {
if (err.message.match(/ERC721:.*nonexistent/)) {
return null;
} else {
throw err;
}
}
} Note that I'm giving an explicit |
Beta Was this translation helpful? Give feedback.
-
Alas, the workaround doesn't always work. It often (but not always) abends the script with I think there's an |
Beta Was this translation helpful? Give feedback.
-
At the moment it only fails when run using HardHat's provider (several wrappers involved), not when using Ethers' |
Beta Was this translation helpful? Give feedback.
-
Here's a standalone example: const {
CONTRACT_ADDRESS = "0x198478f870d97d62d640368d111b979d7ca3c38f", // https://opensea.io/collection/8sian-main-collection (on Ethereum)
PRIVATE_KEY,
INFURA_KEY,
} = process.env;
const ABI = [
"function ownerOf(uint256 id) view returns (address)",
"function totalSupply() view returns (uint256)",
];
async function main() {
let signer, provider;
const useHardhat = true;
if (useHardhat) {
// using HardHat's provider fails
signer = (await ethers.getSigners())[0];
provider = signer.provider;
} else {
// using JsonRpcProvider directly works OK
provider = new ethers.providers.JsonRpcProvider("https://mainnet.infura.io/v3/" + INFURA_KEY);
signer = new ethers.Wallet(PRIVATE_KEY, provider);
}
const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, provider); // or use signer
async function getOwner(id) {
try {
console.log("getOwner -- fetching owner of token #", id);
return await contract.ownerOf(id);
} catch (err) {
console.log("getOwner -- err.message:", err.message);
if (err.error) {
console.log("getOwner -- err.error.message:", err.error.message);
}
// uncomment for workaround
// if (err.error && err.code === "UNPREDICTABLE_GAS_LIMIT") {
// err = err.error;
// }
if (err.message?.match(/ERC721:.*nonexistent/)) {
return null;
} else {
throw err;
}
}
}
console.log("Total supply is:", Number(await contract.totalSupply()));
const tokenId = 0; // fails
// const tokenId = 1; // succeeds
console.log("Owner of token is:", await getOwner(tokenId));
}
main()
.then(() => {
console.log("Completed normally.");
process.exit();
})
.catch((err) => {
console.log("Error!", err);
process.exit(1);
}); |
Beta Was this translation helpful? Give feedback.
-
In both cases, I run the script with require("@nomiclabs/hardhat-waffle");
require("dotenv").config();
const { INFURA_KEY, PRIVATE_KEY } = process.env;
/**
* @type import('hardhat/config').HardhatUserConfig
*/
module.exports = {
solidity: {
version: "0.8.12",
settings: {
optimizer: {
enabled: true,
runs: 100,
},
},
},
networks: {
mainnet: {
chainId: 1,
url: "https://mainnet.infura.io/v3/" + INFURA_KEY,
accounts: [PRIVATE_KEY],
},
polygon_infura: {
chainId: 137,
url: "https://polygon-mainnet.infura.io/v3/" + INFURA_KEY,
accounts: [PRIVATE_KEY],
gas: 100000
},
polygon: {
chainId: 137,
url: "https://polygon-rpc.com/",
accounts: [PRIVATE_KEY]
},
},
}; |
Beta Was this translation helpful? Give feedback.
-
With
Note that the nested error message is With
Note that the error message (which did not get wrapped) is |
Beta Was this translation helpful? Give feedback.
-
Can anyone come up with a concise example (please don't link to other repos or overly complex examples ;)) that demonstrates this outside of Hardhat? I tried the example in the OP (FYI to other trying to reproduce it, I found the network is Rinkeby), and it works for me on https://playground.ethers.org: > provider = ethers.getDefaultProvider("rinkeby")
> CONTRACT = "0x10539a06b047259f247f8c622430c22803821A00"
> ABI = [ 'function stakeOf(address _owner) public view returns (uint256[] memory)' ]
> signer = new VoidSigner("0x10539a06b047259f247f8c622430c22803821A00", provider)
> contract = new ethers.Contract(CONTRACT, ABI, signer);
> contract.stakeOf("0x73257cE508dBB94Ff78C27381FddD42FB7266Ba4", { gasLimit: '50000000', })
[
BigNumber { value: "0" }, BigNumber { value: "2" }, BigNumber { value: "3" }, BigNumber { value: "4" }, BigNumber { value: "5" }, BigNumber { value: "6" }, BigNumber { value: "7" }, BigNumber { value: "8" }, BigNumber { value: "9" }, BigNumber { value: "133" }, BigNumber { value: "137" }, BigNumber { value: "173" }
] |
Beta Was this translation helpful? Give feedback.
-
Describe the bug
I'm trying to call a contract method with an unpredictable gas limit, however if I try to call it and pass the
gasLimit
manually I get get a "Error: cannot estimate gas; transaction may fail or may require manual gas limit" error.Maybe I'm missing something but shouldn't ethers skip estimating gas if it's passed manually?
Reproduction steps
You can test with the following contract in rinkeby:
Result
If I try to simulate the transaction on Tederly it works fine which makes me think their implementation does set the gasLimit fine.
Environment:
Node: v14.17.4
This happens in both node and browser environments.
Search Terms
gas limit, estimate gas
Beta Was this translation helpful? Give feedback.
All reactions