Unable to make a token transfer - ethereum

I'm trying to simply transfer tokens from one address to another on ropsten but i keep getting this error
Returned error: The method eth_sendTransaction does not exist/is not available
this is the code:
const cacheAddress_ = "0xDD963fCdD32ccC802470CdB85A634dE8A47E9257"
const circulationAddress_ = "0x2dA320D8efF599f11Fe575124020743c9c2E8088"
var web3 = new Web3(new Web3.providers.HttpProvider("https://ropsten.infura.io/v3/API_KEY"))
async function transfer() {
const contract = new web3.eth.Contract(lvn.ABI, lvn.address)
const block = await contract.methods.transfer(circulationAddress_, new BigNumber(10**9*10**18)).send({ from: cacheAddress_ })
const circulationBalance = await contract.methods.balanceOf(circulationAddress_).call()
const cacheBalance = await getCacheBalance()
console.log({ circulationBalance, cacheBalance })
}
transfer()
I know it's not a problem with infura, Infura definitely exposes the necessary API's for making transactions. I've tried on a local node with rinkeby and i get the same problem. This is not a duplicate of this question because the same error occurs with web3.eth.personal.unlockAccount still comes up as unavailable (same error as above).
Any help with this would be greatly appreciated.
One solve might be to sign the token transfer if anybody knows how to do that (i know how to sign a regular eth transaction but not a token transfer)

Related

Reading smart contract function - what am I doing wrong?

I'm trying to read total supply from this smart contract, I have checked the ABI and the read does not require arguments. Why am I getting this error?
Imported the ABI from Etherscan with a valid API key
Connected Infura node with valid api.
Please help. I'm new!
Error:
Error: call revert exception [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (method="TOTAL_SUPPLY()", data="0x", errorArgs=null, errorName=null, errorSignature=null, reason=null, code=CALL_EXCEPTION, version=abi/5.7.0)
reason: null,
code: 'CALL_EXCEPTION',
method: 'TOTAL_SUPPLY()',
data: '0x',
errorArgs: null,
errorName: null,
errorSignature: null,
address: '0xFc7a5BD22dFc48565D6f04698E566Dd0C71d3155',
args: [],
transaction: {
data: '0x902d55a5',
to: '0xFc7a5BD22dFc48565D6f04698E566Dd0C71d3155',
from: '0xa9519a76981489Cf44a6b1023C53EA674B9365fB'
}
}
CODE:
const ethers = require("ethers");
async function main() {
// make an API call to the ABIs endpoint
const response = await fetch('https://api.etherscan.io/api?module=contract&action=getabi&address=0x31Cd7378715174e2c5Bd7EDF9984c9bC2A9209Eb&apikey=xxx');
const data = await response.json();
let abi = data.result;
/*console.log(abi);*/
// creating a new Provider, and passing in our node URL
const node = "https://mainnet.infura.io/v3/xxx";
const provider = new ethers.providers.JsonRpcProvider(node);
// initiating a new Wallet, passing in our private key to sign transactions
let privatekey = "xxx";
let wallet = new ethers.Wallet(privatekey, provider);
// print the wallet address
console.log("Using wallet address " + wallet.address);
// specifying the deployed contract address
let contractaddress = "0xFc7a5BD22dFc48565D6f04698E566Dd0C71d3155";
// initiating a new Contract
let contract = new ethers.Contract(contractaddress, abi, wallet);
console.log("Using contract address " + contract.address);
// calling the "retrieve" function to read the stored value
let supply = await contract.TOTAL_SUPPLY();
console.log("Value stored in contract is " + supply.toString());
You're retrieving ABI of address 0x31Cd7378715174e2c5Bd7EDF9984c9bC2A9209Eb on the Ethereum mainnet.
Your ethers provider correctly connects to the Ethereum mainnet.
But then it's trying to interact (call function TOTAL_SUPPLY()) with contract on address 0xFc7a5BD22dFc48565D6f04698E566Dd0C71d3155.
Since there's no contract on the 0xFc... address on the Ethereum mainnet, the call fails.
Have u tried web3client.app.
You can test any abi methods across 500+ chains in any smart contracts.
Identify which network your contract resides and do test it out.
It has code generate feature that lets you to easily get a bug free high quality code

Error: reverted with reason string 'Blacklistable: account is blacklisted'

In my Hardhat test I'm trying to impersonate a USDC account so I can transfer USDC to a test address. The problem is no matter what address I try to impersonate, I always get the following error:
Error: VM Exception while processing transaction: reverted with reason string 'Blacklistable: account is blacklisted'
Here's the relevant code:
it("USDC Test", async function () {
const provider = ethers.provider;
const USDC = new ethers.Contract(addresses.tokens.usdc, abis.ERC20, provider);
// Impersonate USDC whale
await network.provider.request({
method: "hardhat_impersonateAccount",
params: [addresses.whales.usdc],
});
const usdcWhale = await ethers.provider.getSigner(addresses.whales.usdc);
// Approve and transfer USDC to test address
await USDC.connect(usdcWhale).approve(addresses.tokens.usdc, 10000);
await USDC.connect(usdcWhale).transfer(addresses.test.address1, 10000)
});
Any ideas on how to fix this error? I'm certain the addresses I'm using aren't actually blacklisted considering they recently transferred USDC on etherscan.
I realized my mistake. This line was causing the error:
await USDC.connect(usdcWhale).approve(addresses.tokens.usdc, 10000);
I originally thought I needed to approve the USDC contract itself to spend my tokens, however it's not needed if I'm just calling the transfer() function.
Removing this line fixed the error.

Error: invalid BigNumber value (argument="value", value={"value":"25000000000000000"}, code=INVALID_ARGUMENT, version=bignumber/5.5.0)

I have tried changing the values from 0.025 ether to 1 ether then also its showing the same error.
Also, I have tried with the rational number like 1/8 still not working.
LOOKED into some answers but they didn't resolve the error.
I have the same code in other project and it's working over there.
Error Which I received
Uncaught (in promise) Error: invalid BigNumber value (argument="value", value={"value":"25000000000000000"}, code=INVALID_ARGUMENT, version=bignumber/5.5.0)
Could not get the stack frames of error: TypeError: Cannot read properties of null (reading 'length')
Image of the Error
Here is my Code for the Listing Price
uint256 listingPrice = 0.025 ether ; // Here ether is denoting the MATIC
function getListingPrice() public view returns (uint256) {
return listingPrice;
}
Here is the Code for fetching the value in UI
async function putItem(url) {
const web3Modal = new Web3Modal();
const connection = await web3Modal.connect();
const provider = new ethers.providers.Web3Provider(connection);
const signer = provider.getSigner();
const { royalty } = formInput;
//NFT Contract
let contract = new ethers.Contract(nftAddress, NFT.abi, signer);
//minting the certificate
let transaction = await contract.createToken(url);
//waiting for the minting transaction to finish
let tx = await transaction.wait();
let event = tx.events[0];
let value = event.args[2];
let tokenId = value.toNumber(); //Token Id Of the NFT
console.log(tokenId)
//NFT Market Contract
contract = new ethers.Contract(nftMarketAddress, NFTMarket.abi, signer);
//fetching listing price from the contract
let listingPrice = await contract.getListingPrice();
listingPrice = listingPrice.toString();
//listing the certificate.
transaction = await contract.createMarketItem(
nftAddress,
tokenId,
{ value: (listingPrice) },
royalty,
index
);
//waiting for the transaction to complete
await transaction.wait();
console.log("completed")
//navigate back to home page
}
If any more detail required, please comment.
It looks like you're trying to send an object as the parameter { value: (listingPrice) }
This should probably be written as either an array of parameters or just the listingPrice
//listing the certificate.
transaction = await contract.createMarketItem(
nftAddress,
tokenId,
listingPrice,
royalty,
index
);
Source: https://docs.ethers.io/v5/api/contract/contract/#contract-functionsSend
For my case I needed to add .toString() to the BigNumber before passing it to the contract.
async changePayoutAmount_ether(amount_ether) {
let amount_wei = new BigNumber(amount_ether).shiftedBy(18).toString()
await this.state.pcrContract.methods.setPayoutAmount(amount_wei).send({from: this.state.account}).then(console.log)
}
Also for anyone troubleshooting, note that there are at least two BigNumber libraries: I believe this error comes from this one but be careful if you're reading docs from the ethers.js one because the syntax for the constructors is different.
I got this error as well. In my case, I forgot to update the ABI.
You can use the following module:
import converter form "ethereum-uint-converter"
And if you want to know more detail, click here.
I think this is the issue:
transaction = await contract.createMarketItem(
nftAddress,
tokenId,
{ value: (listingPrice) },
royalty,
index
);
{ value: (listingPrice) }, is supposed to be object that represents the amount of money you are sending along side the transaction and it should be the last parameter in the function. Because looks like you are creating an NFT market item and you have to pay the price of listing.
Since you are creating an nft, looks like you have a const { royalty } = formInput. I believe you wanted to send the nft price instead of { value: (listingPrice) }. so your transaction should be like this
transaction = await contract.createMarketItem(
nftAddress,
tokenId,
// I assume you want to send the nft price here from form
priceFromForm,
royalty,
index,
// this should be the last parameter
{ value: (listingPrice) }
);

I need a simple way to sign data via web3 and metamask

I need a very simple way to sign data with Metamask and Web3. I am very familiar with using eth account sign with Web3, but I want to incorporate Metamask into it. I have read the Metamask docs on signing data, but the examples they gave are outdated.
The one thing I have done: Successfully enabled Ethereum and got access to the user's address who connected.
Any suggestions on a very very simple way to sign data? I'm really just testing things out Metamask and want to get started.
const getSignedData = async () => {
const messageToSign = "any message you create or fetch";
const accounts = (await ethereum?.request({
method: "eth_requestAccounts",
})) as string[];
// account will be the signer of this message
const account = accounts[0];
// password is the third param as uuid
const signedData = await ethereum?.request({
method: "personal_sign",
params: [
JSON.stringify(messageToSign.data),
account,
messageToSign.data.id,
],
});
return { signedData, account };
};

Using local private key with Web3.js

How can I interact with smart contracts and send transactions with Web3.js by having a local private key? The private key is either hardcoded or comes from an environment (.env) file?
This is needed for Node.js and server-side interaction or batch jobs with Ethereum/Polygon/Binance Smart Chain smart contracts.
You may encounter e.g. the error
Error: The method eth_sendTransaction does not exist/is not available
Ethereum node providers like Infura, QuikNode and others require you to sign outgoing transactions locally before you broadcast them through their node.
Web3.js does not have this function built-in. You need to use #truffle/hdwallet-provider package as a middleware for your Ethereum provider.
Example in TypeScript:
const Web3 = require('web3');
const HDWalletProvider = require("#truffle/hdwallet-provider");
import { abi } from "../../build/contracts/AnythingTruffleCompiled.json";
//
// Project secrets are hardcoded here
// - do not do this in real life
//
// No 0x prefix
const myPrivateKeyHex = "123123123";
const infuraProjectId = "123123123";
const provider = new Web3.providers.HttpProvider(`https://mainnet.infura.io/v3/${infuraProjectId}`);
// Create web3.js middleware that signs transactions locally
const localKeyProvider = new HDWalletProvider({
privateKeys: [myPrivateKeyHex],
providerOrUrl: provider,
});
const web3 = new Web3(localKeyProvider);
const myAccount = web3.eth.accounts.privateKeyToAccount(myPrivateKeyHex);
// Interact with existing, already deployed, smart contract on Ethereum mainnet
const address = '0x123123123123123123';
const myContract = new web3.eth.Contract(abi as any, address);
// Some example calls how to read data from the smart contract
const currentDuration = await myContract.methods.stakingTime().call();
const currentAmount = await myContract.methods.stakingAmount().call();
console.log('Transaction signer account is', myAccount.address, ', smart contract is', address);
console.log('Starting transaction now');
// Approve this balance to be used for the token swap
const receipt = await myContract.methods.myMethod(1, 2).send({ from: myAccount.address });
console.log('TX receipt', receipt);
You need to also avoid to commit your private key to any Github repository. A dotenv package is a low entry solution for secrets management.
You can achieve what you want by using ethers.js instead of web3 with no other package needed.
First import the library:
Node.js:
npm install --save ethers
const { ethers } = require("ethers");
Web browser:
<script src="https://cdn.ethers.io/lib/ethers-5.2.umd.min.js"
type="application/javascript"></script>
Define the provider. One way is using the provider URL like this:
const provider = new ethers.providers.JsonRpcProvider(rpcProvider);
Then, in order to interact with the contract without asking for authorization, we will create a wallet using the private key and the provider like this:
const signer = new ethers.Wallet(privateKey,provider)
Now, you can create the contract with the address, ABI, and the signer we created in the previous step:
const contract = new ethers.Contract(contractAddress,ABI, signer);
Now, you can interact with the contract directly. For example, getting the balance of a token:
const tokenBalance = await nftContractReadonly.balanceOf(signer.getAddress(),tokenId);
Don't forget to store the private key in a safe place and never hardcode it in a web page.
Further reading: Provider Signer
There is a better and simple way to sign and execute the smart contract function. Here your function is addBonus.
First of all we'll create the smart contract instance:
const createInstance = () => {
const bscProvider = new Web3(
new Web3.providers.HttpProvider(config.get('bscRpcURL')),
);
const web3BSC = new Web3(bscProvider);
const transactionContractInstance = new web3BSC.eth.Contract(
transactionSmartContractABI,
transactionSmartContractAddress,
);
return { web3BSC, transactionContractInstance };
};
Now we'll create a new function to sign and execute out addBonus Function
const updateSmartContract = async (//parameters you need) => {
try {
const contractInstance = createInstance();
// need to calculate gas fees for the addBonus
const gasFees =
await contractInstance.transactionContractInstance.methods
.addBonus(
// all the parameters
)
.estimateGas({ from: publicAddress_of_your_desired_wallet });
const tx = {
// this is the address responsible for this transaction
from: chainpalsPlatformAddress,
// target address, this could be a smart contract address
to: transactionSmartContractAddress,
// gas fees for the transaction
gas: gasFees,
// this encodes the ABI of the method and the arguments
data: await contractInstance.transactionContractInstance.methods
.addBonus(
// all the parameters
)
.encodeABI(),
};
// sign the transaction with a private key. It'll return messageHash, v, r, s, rawTransaction, transactionHash
const signPromise =
await contractInstance.web3BSC.eth.accounts.signTransaction(
tx,
config.get('WALLET_PRIVATE_KEY'),
);
// the rawTransaction here is already serialized so you don't need to serialize it again
// Send the signed txn
const sendTxn =
await contractInstance.web3BSC.eth.sendSignedTransaction(
signPromise.rawTransaction,
);
return Promise.resolve(sendTxn);
} catch(error) {
throw error;
}
}