How can I set the gasPrice in a contract interaction using ethers.js? I'm trying to override the gasPrice in the code below:
let txPromise = contract.populateTransaction.runAdventureVRF(0, false, { gasPrice: 800000 })
walletSigner.sendTransaction(txPromise)
and i'm receiving the error transaction underpriced. If i try to log txPromise.overrides it is undefined, which makes me think the gas price is never being set.
docs
additional code
const provider = new ethers.providers.AlchemyProvider('matic', process.env.ALCHEMY_API_KEY)
const wallet = new ethers.Wallet(process.env.PK)
const abi = '[{"inputs":[{"internalType":"uint256","name":"_teamId","type":"uint256"},{"internalType":"bool","name":"_energy","type":"bool"}],"name":"runAdventureVRF","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]'
const contract = new ethers.Contract(address, abi, provider);
let walletSigner = wallet.connect(provider)
One solution is to add the gas price as an override to your transaction:
walletSigner.sendTransaction(txPromise, {gasPrice: ethers.utils.parseUnits('100', 'gwei'), gasLimit: 1000000});
This is the only solution I could find as getGasPrice() and estimateGas() were returning a empty json array. I don't know if it has to do with the provider (alchemy) or why those are failing.
The specific syntax to override the gas price is here:
Ethers Override Transaction Gas Price Manually
It's also in the following Ethers docs, but not as clear (if you don't know the syntax):
Ethers Contract Functions Send
At the time of this post, the default gas value of all my transactions is 1.5 gwei which is nowhere near enough on the matic network. This will also hang up the transaction indefinitely until you send a new transaction with the same nonce value. Even if you resolve your gas issue, until you deal with the hung transaction, other transactions will stack up behind it.
If you just want to increase gasLimit by a certain amount, you can make a helper function to do so:
const increaseGasLimit = (estimatedGasLimit: BigNumber) => {
return estimatedGasLimit.mul(130).div(100) // increase by 30%
}
And use it like this:
const estimatedGas = await contract.estimateGas.method(args)
const tx = await contract.method(args, { gasLimit: increaseGasLimit(estimatedGas) })
I am trying to read basic information from a smart contract using web3.js (GRAPH Token):
https://etherscan.io/address/0xc944e90c64b2c07662a292be6244bdf05cda44a7#code
This is my super simple react web3.js setup:
import Web3 from 'web3';
...
useEffect(() => {
const start = async () => {
const web3 = new Web3('https://bsc-dataseed1.binance.org:443')
const abi = [{"inputs":[{"internalType":"uint256","name":"_initialSupply","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"MinterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"MinterRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"NewOwnership","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"NewPendingOwnership","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"addMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingGovernor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"removeMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newGovernor","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
const address = '0xc944E90C64B2c07662A292be6244BDf05Cda44a7'
const contract = new web3.eth.Contract(abi, address)
console.log(contract);
const i = await contract.methods.getName().call()
console.log(i); // => ERROR
}
start()
}, [])
And it throws error:
Error: Returned values aren't valid, did it run Out of Gas? You might also see this error if you are not using the correct ABI for the contract you are retrieving data from, requesting data from a block number that does not exist, or querying a node which is not fully synced.
This is a known and misleading error which usually means that the address or the contract abi is invalid but I verified it is correct.
I researched this error for two days but didn't manage to solve this issue... any suggestions?
You're trying to interact with an Ethereum contract, using a BSC (Binance Smart Chain) Web3 provider (in your case https://bsc-dataseed1.binance.org:443). This results in trying to call the getName() function on the BSC address (which doesn't contain any contract).
Ethereum and BSC are different networks, unrelated to each other.
Solution: Use an Ethereum mainnet provider (for example Infura is widely used).
If I only get an Ethereum address from the input, is there a way to find out whether it matches the ERC20 token standard?
ERC165 tackles this problem, but, unfortunately, most ERC20 implementations don't support it (as of Nov 2018, at least OpenZeppelin doesn't). This means that you could try calling the supportsInterface function, but it would revert anyway and you'd rather complicate things.
Nevertheless, here's how it's defined in ERC721:
bytes4 private constant _InterfaceId_ERC721 = 0x80ac58cd;
/*
* 0x80ac58cd ===
* bytes4(keccak256('balanceOf(address)')) ^
* bytes4(keccak256('ownerOf(uint256)')) ^
* bytes4(keccak256('approve(address,uint256)')) ^
* bytes4(keccak256('getApproved(uint256)')) ^
* bytes4(keccak256('setApprovalForAll(address,bool)')) ^
* bytes4(keccak256('isApprovedForAll(address,address)')) ^
* bytes4(keccak256('transferFrom(address,address,uint256)')) ^
* bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^
* bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)'))
*/
Although it's not guaranteed for all implementations to define the interface id, there's a higher chance it will work in the case of ERC721, given the fact the community agreed on applying ERC165 right from the get-go. If the return value of the query below is true, then it means you have a compliant contract, otherwise just revert the transaction.
// you can call this in your contracts
IERC721(contractAddress).supportsInterface(0x80ac58cd)
Also, a useful resource for manually checking the bytes4 of a given method is 4byte.directory
If you are asking about off-chain, so use these functions:
getContract(url, smartContractAddress){
const Web3Eth = require('web3-eth');
const abi_ = this.getABI();
const web3Eth = new Web3Eth(Web3Eth.givenProvider || url);
return new web3Eth.Contract(abi_, smartContractAddress);
}
async getERCtype(contract){
const is721 = await contract.methods.supportsInterface('0x80ac58cd').call();
if(is721){
return "ERC721";
}
const is1155 = await contract.methods.supportsInterface('0xd9b67a26').call();
if(is1155){
return "ERC1155";
}
return undefined;
}
getABI(){
return [
{"constant":true,"inputs": [
{"internalType":"bytes4","name": "","type": "bytes4"}],
"name": "supportsInterface",
"outputs": [{"internalType":"bool","name": "","type": "bool"}],
"payable": false,"stateMutability":"view","type": "function"}
];
}
like this:
const contract = getContract(url, smartContractAddress);
const type = await getERCtype(contract);
console.log(type);
There are many possible ways to achieve this. One possible quick and dirty solution is to check if a ERC20 function exists on the contract address by calling the following:
eth.call({to:contractAddress, data:web3.sha3("balanceOf(address)")})
A non-ERC20 will return a 'null' 0x hex response whereas an ERC20 will give you a 32byte uint, in this case 0 but if you provide an address in the data then it will give you the actual token balance for that address.
This is not a guaranteed way of determining a contract is ERC20 since other contracts may expose the same function, however it is a quick and easy check. You could add additional calls on totalSupply() etc. for more confirmation.
the question states that given an Ethereum address, is this an Ethereum contract address or not?
First thing, you have to decide if this address is a contract address or an externally owned account address. How to find out if an Ethereum address is a contract
If it is a contract address, then you can only get the bytecode that is stored in the blockchain. Now you have to reverse engineer the bytecode to get the contract functions but this is almost impossible. There are some decompilers but they are not perfectly creating the contract code from the bytecode.
ERC165 just checks if the current contract signature supports the given interfaceId or not. Since you have only ethereum address, this will not help in this question.