Uncaught (in promise) Error: call revert exception - blockchain

Uncaught (in promise) Error: call revert exception [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (method="name()", data="0x", errorArgs=null, errorName=null, errorSignature=null, reason=null, code=CALL_EXCEPTION, version=abi/5.7.0)
const provider = new ethers.providers.Web3Provider(window.ethereum);
const address = '0x6B175474E89094C44Da98b954EedeAC495271d0F'
const abi = [
"function name() view returns (string)",
"function symbol() view returns (string)",
"function totalSupply() view returns (uint256)"
]
const connectWallet = (async()=>{
await provider.send("eth_requestAccounts",[]);
})
const contract = new ethers.Contract(address,abi,provider);
const getInfo = (async()=>{
const n = await contract.name();
console.log(n)
})
I am trying to read the contract but why I am getting this error ? and how can i solve it??

There is a contract deployed on the specified address only on the Ethereum mainnet. But this address doesn't hold any contract on other networks.
Since you're using the window.ethereum provider published by MetaMask or another browser wallet extension, the call is sent on the network that is currently selected in the wallet.
So if you select the Ethereum mainnet, the call succeeds. In all other cases, the call fails because there is no contract on the selected network that could respond to the call.

Related

How to correctly set up a WebSocketProvider in ethers.js?

I'm trying to switch my dapp from Web3Provider to WebSocketProvider,
form this:
const provider = new ethers.providers.Web3Provider(window.ethereum)
const accounts = await window.ethereum.request({ method: "eth_accounts" })
const account = accounts[0]
const signer = provider.getSigner()
to this:
const provider = new ethers.providers.WebSocketProvider("ws://localhost:8545") <-
const accounts = await window.ethereum.request({ method: "eth_accounts" })
const account = accounts[0]
const signer = provider.getSigner()
With this change I can interact with the Contract only with account that creates and deploy the smart contract, also, the transactions have no confirmation from the user. However, when I try to call some Contract function with another address I get this error:
On the fourth line, the value of the "from" key is different from the address actually selected in the metamask, in fact it is the address of the creator of the Smart Contract. There seems to be some problem with the signer or what? With Web3Provider everything works fine.
Can you help me in any way or tell me more about WebSocketProvider?
Thanks in advance

Paying with ERC20 token

I want to build an NFT that I can paid with an ERC-20 token to mint it. I'm using currently the Mumbai testnet on polygon, and I'm using the Dummy ERC20 token to test it out.
This is currently my constructor:
ERC20 token;
constructor() ERC721("Token", "TKN") {
token = ERC20(0xfe4F5145f6e09952a5ba9e956ED0C25e3Fa4c7F1);
}
And this is my mint function:
function mint() public returns (uint256) {
uint256 tokenId = _tokenIds.current();
require(tokenId <= MAX_TOKEN_ID);
token.approve(address(this), NFT_PRICE);
token.transfer(address(this), NFT_PRICE);
_mint(msg.sender, tokenId);
_setTokenURI(tokenId, TOKEN_URI);
_tokenIds.increment();
return tokenId;
}
If I remove those 2 lines the code works fine, it mints the NFT:
token.approve(address(this), NFT_PRICE);
token.transfer(address(this), NFT_PRICE);
But as soon as I add it, the code breaks, it gives me the following gas estimation error:
The transaction execution will likely fail. Do you want to force sending?
Internal JSON-RPC error. { "code": 3, "message": "execution reverted: ERC20: transfer amount exceeds balance", "data": "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002645524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63650000000000000000000000000000000000000000000000000000" }
As a troubleshooting step I've also added this inside my mint function to make sure I'm calling from my own wallet:
sender = msg.sender;
And created this function:
function tokenBalance(address addr) public view returns (uint256) {
return token.balanceOf(addr);
}
And if I grab the token balance of the sender address it gives me the value:
0: uint256: 2000000000000000000
It's because the logic is wrong. That approve function you call inside your mint function is useless: the spender needs to call the approve function from the the contract of your dummy ERC20.
And then you can call the transferFrom(msg.sender, address(this), NFT_PRICE) from your mint function.

Unable to call safeTransferFrom method from a JS api file

I have deployed my ERC721 contract on polygon testnet from owner(ox43b....81). I have created a small node server to interact with my contract through web3. I m using truffle config
//truffle-config.js
polygon-testnet: {
provider: new HDWalletProvider(privateKey, https://rpc-mumbai.maticvigil.com),
network_id: 80001,
gas: 6000000,
gasPrice: 10000000000,
confirmations: 2,
timeoutBlocks: 200,
skipDryRun: true
}
//index.js file
function test(){
const owner = await myContract.methods.owner().call()
console.log('contract owner', owner) //ox43b....81
//miniting token
const mint = await myContract.methods
.safeMint(owner,1001, 'google.com')
.send({ from: owner, gas: 100000 }) // is this the write way of calling ??
//token transfer
const transfer = await myContract.methods
.safeTransferFrom(acc1, acc2, 1003)
.send({ from: acc1, gas: 1000000 }) // is this the write way of calling ??
}
bcz i m getting err in both function calling: Error: Returned error: unknown account.
NOTE: I am not calling my contract func from truffle console. I m calling through a JS api file index.js
I know there is another way by using web3.eth.accounts.signTransaction() to mint & transfer the token.
Q.1 Is signing is reqd? Can't we access the contract method directly as i did above ?
Q.2 By using web3.eth.accounts.signTransaction() method i can able to mint the tokens successfully but i am facing issue in token transfer (using safeTransferFrom()). There are two cases:
case 1: i am transferring the token which is created/minted by contract owner(ox43b....81) to any other individual user address.
const fromAddress = 'ox43b....81' //owner of the contract
const toAddress = '0x26....7D'
const tokenId = 10001 // created by owner(ox43b....81)
const tx = {
from: ownerAddress, // ox43b....81 --> owner who created contract
to: contractAddress,// 0xfe.....24
nonce: nonce, // nonce with the no of transactions from our owner address
gas: 1000000, // fee estimate to complete the transaction
data: await myContract.methods
.safeTransferFrom(fromAddress, toAddress, tokenId)
.encodeABI()
}
// do signing stuff & send it
so in this case i m able to transfer the token successfully.
case 2: i am transferring the token which is created/minted by another(not contract owner) user(0x26....7D) to any other individual user address / or to owner.
const fromAddress = '0x26....7D' (not the owner of contract)
const toAnyAddress = '0x5e....5a' // any other user
const tokenId = 10002 // created by user '0x26....7D' (not the owner of contract)
const nonce = await web3.eth.getTransactionCount(fromAddress, 'latest')
const tx = {
from: fromAddress, // 0x26....7D -> is this right? or i put contract owner adr?
to: contractAddress,// 0xfe.....24
nonce: nonce,
gas: 1000000, // fee estimate to complete the transaction
data: await this.myContract.methods
.safeTransferFrom(fromAddress, toAnyAddress, tokenId)
.encodeABI()
}
// do signing stuff & send it
so in this case i m getting err - Fail with error 'ERC721: transfer caller is not owner nor approved'.
I need solution for my case 2. Is there something related with locked/unlocked accounts? How can i fix it?
Please help! Thanks in advance.
Q.1 Is signing is reqd? Can't we access the contract method directly as i did above ?
The .send() method of the web3 Contract instance performs/requests the signature in the background. So it's always signed - just not with an explicit "sign" keyword in the code in this case.
Q.2 There are two cases:
This is not related to the way you sign the transaction.
The second case fails because the token holder has not approved the spender (i.e. the transaction sender) to spend their tokens.
You need to invoke the approve(<spender>, <tokenId>) function from the token holder address first, to be able to successfully use the transferFrom().
// assuming `acc1` is holder of the token ID `1003`
// approve the `owner` to spend the `acc1`'s token
await myContract.methods.approve(owner, 1003).send({from: acc1});
// transfer token `1003` held by `acc1` ... and send the transaction from the `owner` address
await myContract.methods.transferFrom(acc1, recipient, 1003).send({from: owner});

Error creating contract after getting contract ABI from Etherscan API

I am trying to get the contract ABI using the Etherscan API, and then create a contract instance and call a method. I am able to get the ABI from Etherscan but when creating the contract object I am getting this error: "You must provide the json interface of the contract when instantiating a contract object."
This is what my code looks like
let url = 'https://api.etherscan.io/api?module=contract&action=getabi&address=0x672C1f1C978b8FD1E9AE18e25D0E55176824989c&apikey=<api-key>';
request(url, (err, res, body) => {
if (err) {
console.log(err);
}
let data = JSON.parse(body);
let contract_abi = data.result;
console.log(contract_abi)
let contract_address = '0x672C1f1C978b8FD1E9AE18e25D0E55176824989';
const contract = new web3.eth.Contract(contract_abi);
const contract_instance = contract.at(contract_address);
// Call contract method
})
When I console.log the contract_abi I see the ABI data. I've also tried creating the contract by doing
const contract = new web3.eth.Contract(contract_abi, contract_address)
Thanks!
data.result contains the JSON ABI as a string. You need to decode it as well to an object.
let contract_abi = JSON.parse(data.result);
Also, it's possible that you're using a deprecated version of Web3 that supports the contract.at() syntax.
But if you're using the current version, you'd get the contract.at is not a function error. In that case, you need to pass the address as the second argument of the Contract constructor.
const contract = new web3.eth.Contract(contract_abi, contract_address);

Ethereum Web3.js Invalid JSON RPC response: ""

I am using web3.js module for ethereum. While executing a transaction I am getting error response.
Error:
"Error: Invalid JSON RPC response: ""
at Object.InvalidResponse (/home/akshay/WS/ethereum/node_modules/web3-core-helpers/src/errors.js:42:16)
at XMLHttpRequest.request.onreadystatechange (/home/akshay/WS/ethereum/node_modules/web3-providers-http/src/index.js:73:32)
at XMLHttpRequestEventTarget.dispatchEvent (/home/akshay/WS/ethereum/node_modules/xhr2/lib/xhr2.js:64:18)
at XMLHttpRequest._setReadyState (/home/akshay/WS/ethereum/node_modules/xhr2/lib/xhr2.js:354:12)
at XMLHttpRequest._onHttpResponseEnd (/home/akshay/WS/ethereum/node_modules/xhr2/lib/xhr2.js:509:12)
at IncomingMessage.<anonymous> (/home/akshay/WS/ethereum/node_modules/xhr2/lib/xhr2.js:469:24)
at emitNone (events.js:111:20)
at IncomingMessage.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickCallback (internal/process/next_tick.js:180:9)"
I am using ropsten test network url for testing my smart contract:
https://ropsten.infura.io/API_KEY_HERE
When I call the balanceOf function, it works fine but when I try to call function transfer it send me this error. The code is mentioned below:
router.post('/transfer', (req, res, next)=>{
contractInstance.methods.transfer(req.body.address, req.body.amount).send({from:ownerAccountAddress})
.on('transactionHash',(hash)=>{
console.log(hash)
}).on('confirmation',(confirmationNumber, receipt)=>{
console.log(confirmationNumber)
console.log(receipt)
}).on('receipt', (receipt)=>{
console.log(receipt)
}).on('error',(err)=>{
console.log(err)
})
})
Please let me know where I am wrong.
EDIT: I am using web3js version "web3": "^1.0.0-beta.34"
To add to what maptuhec said, while calling a "state-changing" function in Web3 or a state-changing transaction, it MUST be SIGNED!
Below is an example of when you're trying to call a public function (or even a public contract variable), which is only reading (or "view"ing) and returning a value from your smart contract and NOT changing its state, in this we don't need to necessarily specify a transaction body and then sign it as a transaction, because it doesn't change the state of our contract.
contractInstance.methods.aPublicFunctionOrVariableName().call().then( (result) => {console.log(result);})
**
State-Changing Transactions
**
Now, consider the example below, here we're trying to invoke a "state-changing" function and hence we'll be specifying a proper transaction structure for it.
web3.eth.getTransactionCount(functioncalleraddress).then( (nonce) => {
let encodedABI = contractInstance.methods.statechangingfunction().encodeABI();
contractInstance.methods.statechangingfunction().estimateGas({ from: calleraddress }, (error, gasEstimate) => {
let tx = {
to: contractAddress,
gas: gasEstimate,
data: encodedABI,
nonce: nonce
};
web3.eth.accounts.signTransaction(tx, privateKey, (err, resp) => {
if (resp == null) {console.log("Error!");
} else {
let tran = web3.eth.sendSignedTransaction(resp.rawTransaction);
tran.on('transactionHash', (txhash) => {console.log("Tx Hash: "+ txhash);});
For more on signTransaction, sendSignedTransaction, getTransactionCount and estimateGas
when using Web3.js you should sign the transactions. When you call functions which are non-constant, like transfer, you should sign the transaction and after that send the signed transaction (there is a method called sendSignedTransaction). This is very hard using web3js, I recommend using ehtersjs, with it everything is a lot easier.
in my case, it's the network problem.
I set the HTTP_PROXY and HTTPS_PROXY in my terminal and can successfully curl google.com, however I got this error.
solution:
I ssh to another server (located in HK where network is good to connect everywhere in the world ) and everything is fine.