web3 balanceOf always 0 - ethereum

I'm trying to get the balance of an address on my smart contract using web3, but the balance is always 0. Using metamask on Rinkeby since my contract is deployed on rinkeby. https://rinkeby.etherscan.io/address/0x8e3a88be716ce7c8119c36558ec97bc634592255
You can verify the wallet has a balance by putting it in the balanceOf function on etherScan. Use the address 0x8b54A82a12bD5A7bA33B4842cA677E55f78a8612
let provider = web3.currentProvider;
web3 = new Web3(provider);
let abi = 'too long of a string to post here';
let MyContract = web3.eth.contract(JSON.parse(abi));
let myContractInstance = MyContract.at('0x8e3a88be716ce7c8119c36558ec97bc634592255');
let address = '0x8b54A82a12bD5A7bA33B4842cA677E55f78a8612';
function balanceOf(address) {
if (!address) {
return;
}
this.myContractInstance.balanceOf.call(address, function(error, balance) {
if (error) {
return;
}
alert(balance.c[0] + ' RHC');
});
}
balanceOf(address);
Here is the getBalance function on my contract
function balanceOf(address _owner) public view returns (uint256 balance) {
return balances[_owner];
}
Website implemented on http://robinhoodcoin.net/metamask.html
Code https://github.com/robinhoodcoin/robinhoodcoin.github.io/blob/master/metamask.html
EDIT
when I change the provider to be the following:
var web3 = new Web3(new Web3.providers.HttpProvider('https://rinkeby.infura.io/'));
I am able to get the balance. SO there is something up with using metamask as the provider.

The line at https://github.com/robinhoodcoin/robinhoodcoin.github.io/blob/master/metamask.html#L118 has a typo. It reads:
self.myContractInstance = self.MyContract.at(self.address);
but the address is stored at self.contractAddress, so it should read:
self.myContractInstance = self.MyContract.at(self.contractAddress);
After making that fix, the page works fine for me with MetaMask.

Related

Unable to create contract clone on Hardhat. "Error: Transaction reverted: function call to a non-contract account"

I'm trying to create a clone using OpenZeppelin Clones library. However, it seems that hardhat is not able to recognize the created clone contracts address.
The same code works on Remix, so does this have something to with Hardhat? NOTE: I have tried using Ganache as well, however it reverts with the same error.
Here is my factory contract:
contract WhoopyFactory {
address immutable implementationContract;
address[] public allClones;
event NewClone(address indexed _instance);
mapping(address => address) public whoopyList;
constructor() {
implementationContract = address (new Whoopy());
}
function createClone(address _whoopyCreator) payable external returns(address) { address clone = Clones.clone(implementationContract); Whoopy(clone).initialize(_whoopyCreator);
emit NewClone(clone);
return clone;
}
And here is the test I am running:
describe("Whoopy + WhoopyFactory", function () {
it("Initialises contract correctly", async function () {
const provider = new ethers.providers.JsonRpcProvider("HTTP://127.0.0.1:7545")
const deployer = provider.getSigner(0);
const player = provider.getSigner(1);
Whoopy = await ethers.getContractFactory("Whoopy")
whoopy = await Whoopy.deploy()
await whoopy.deployed()
WhoopyFactory = await ethers.getContractFactory("WhoopyFactory")
wf = await WhoopyFactory.deploy()
await wf.deployed()
wf.connect(player)
const tx = await wf.createClone("0x70997970C51812dc3A010C7d01b50e0d17dc79C8")
console.log(tx)
const txReceipt = await tx.wait(1)
console.log(txReceipt)
This is the error which reverts:
Error: Transaction reverted: function call to a non-contract account
at Whoopy.initialize (contracts/Whoopy.sol:117)
at <UnrecognizedContract>.<unknown> (0x9f1ac54bef0dd2f6f3462ea0fa94fc62300d3a8e)
As I said before, this code works correctly on Remix. Hope someone can point me in the right direction. Thanks in advance!
From what I understood, you are deploying a smart contract on Ganache, you can use hardhat's own local chain, by doing yarn chain, or npx hardhat node, and change the port to 8545.
You can make it more simpler by replacing the following
const provider = new ethers.providers.JsonRpcProvider("HTTP://127.0.0.1:7545")
const deployer = provider.getSigner(0);
const player = provider.getSigner(1);
with
const accounts = await hre.ethers.getSigners();
const deployer = accounts[0];
const player = accounts[1];
and while deploying use npx hardhat test --network localhost

How to send ETH to a contract function with ethers.js?

I am trying to send ETH to a contract function from a web app via metamask and ethers.js. So far I have tried:
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const splitterManager = new ethers.Contract(contract.address, contract.abi, signer);
var overrides = {value: 5}
const result = await splitterManager.newSplitter(addresses, shares, erc20, overrides);
console.log(result);
But I keep getting 'Error: resolver or addr is not configured for ENS name (argument="name", value="", code=INVALID_ARGUMENT, version=contracts/5.2.0)'.
You can call the contracts function and pass it an object containing a value key.
contractInstance.testFunction(<any function args>, { value: ethers.utils.parseUnits("1", "ether") });
This would call your contract's function and send that amount of wei to the contract.
function testFunction() public payable {
// contract code
}
If the contract has implemented the receive function, you can send ether to a contract same as sending ether to any other account. Here's a short example:
const accounts = await provider.listAccounts();
const signer = provider.getSigner(accounts[0]);
tx = {
to: **CONTRACT_ADDRESS**,
value: ethers.utils.parseEther('2', 'ether')
};
const transaction = await signer.sendTransaction(tx);
await contractInstance
.connect(rpcProvider)
.function({
value: ethers.utils.parseUnits("1","ether")
});
this should work
some address is an invalid address it could be the contract.address, the addresses, or some other address

Check balance of ERC20 token in Hardhat using Ethers.js

I'm writing unit tests using Hardhat's mainnet fork, and for a test I want to check the owner account's initial balance of an ERC20 token, in particular DAI. Here's my test so far:
const { ethers } = require("hardhat");
describe("Simple Test", function () {
it("Check balance of DAI", async function () {
const provider = ethers.provider;
const [owner] = await ethers.getSigners();
// Want to get initial DAI balance here so it can be compared later
});
});
What's a simple way to do this?
Found what I was looking for. First thing I did was save the DAI contract address at the top:
const DAI_ADDRESS = "0x6b175474e89094c44da98b954eedeac495271d0f";
Then I had to use the ERC20 token ABI, which I placed in the same folder as my test:
const ERC20ABI = require('./ERC20.json');
Then to get the owner account's DAI balance I just called balanceOf() from the DAI contract:
const DAI = new ethers.Contract(DAI_ADDRESS, ERC20ABI, provider);
DAIBalance = await DAI.balanceOf(owner.address);
This should work for any ERC20 token as well.

How to interact with the deployed ERC20(openzeppelin ERC20 contract) token and transfer token from user address X to address Y?

I've created a simple Contract extending openzeppelin ERC20.
I'm trying to transfer token from one address to another.
Contract code is as below:
File name: Token.sol
pragma solidity ^0.7.0;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
contract Token is ERC20 {
uint256 public INITIAL_SUPPLY = 100000;
constructor() ERC20("My Token", "MYT") {
_mint(msg.sender, INITIAL_SUPPLY);
}
}
Code within test file:
const { expect } = require("chai");
describe("Send token from second address in the block", function () {
it("Send 100 MYT to the third account", async function () {
const Token = await ethers.getContractFactory("Token");
const token = await Token.deploy();
// get accounts from the network
const [owner, secondAccount, thirdAccount] = await ethers.getSigners();
// send some credit to the second account
await token.transfer(secondAccount.address, 500);
// Approve token transfer
await token.approve(secondAccount.address, 200);
// Transfer credit from second account to the third account (This step is not working)
await token.transferFrom(secondAccount.address, thirdAccount.address, 100);
});
});
Error received:
Error: VM Exception while processing transaction: reverted with reason string 'ERC20: transfer amount exceeds allowance'
at Token.sub (#openzeppelin/contracts/math/SafeMath.sol:171)
at Token.transferFrom (#openzeppelin/contracts/token/ERC20/ERC20.sol:154)
at processTicksAndRejections (internal/process/task_queues.js:94:5)
at runNextTicks (internal/process/task_queues.js:63:3)
at listOnTimeout (internal/timers.js:501:9)
at processTimers (internal/timers.js:475:7)
at EthModule._estimateGasAction (node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:421:9)
at HardhatNetworkProvider.request (node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:105:18)
at EthersProviderWrapper.send (node_modules/#nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20)
Thank you for the help.
If you check Approve if erc20, the function arguments expect address _spender, uint256 _value as arguments. In your case you approved secondAccount to withdraw 200 tokens.
It means secondAccount can transfer those token to his account from the token contract. To do that, you try await token.connect(secondAccount).transferFrom(token.address,secondAccount.address,100);

How to sign an ethereum transaction with metamask

I am currently sending transactions with this code:
const provider = ethers.getDefaultProvider("ropsten", {
infura:
"https://ropsten.infura.io/v3/ee11be9f1d1c43199618db4a7b22aa79",
});
const signer = new ethers.Wallet(PRIVATE_KEY);
const account = signer.connect(provider);
const uniswap = new ethers.Contract(
ropstenUniswapContract,
[
"function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts)",
],
account
);
const gasCost = ethers.BigNumber.from((+gasPrice/10) * Math.pow(10, 9));
console.log('Computed gas cost ->', gasCost);
const tx = await uniswap.swapExactETHForTokens(
amountOutMin,
path,
to,
deadline,
{ value, gasPrice: gasCost }
);
// Transaction Hash and Block
setTransactionHash(tx.hash);
const receipt = await tx.wait();
console.log(receipt);
My question is:
How can I make MetaMask sign the transaction on my behalf instead of supplying my private key?
Transaction signing is abstracted away with web3.js or Ethers.js. You can directly connect your Ethers.js to MetaMask provider (windows.ethereum) in in-page JavaScript code.
An example here.
Your (browser-facing) app can communicate with the MetaMask browser extension using the Ethereum Provider API.
Speficically the eth_sendTransaction method passing it the data field (specifying which function in your contract you want to execute, as well as the passed argument values), along with other params such as the sender address.
If you're new to MetaMask, just a quick note: To get the user's list of addresses, you need to call the eth_requestAccounts method.