I use hardhat to test a solidity contract but I get a different result with functions:
getUserBalance (contract function)
balanceOf
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/utils/Counters.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/utils/math/SafeMath.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "hardhat/console.sol";
contract TestContract is ERC721Enumerable, Ownable {
using SafeMath for uint;
...
function getContractBalance() public view onlyOwner returns (uint) {
return address(this).balance;
}
function getUserBalance(address _owner) external view returns (uint) {
return address(_owner).balance;
}
}
test.js
...
beforeEach(async function () {
Token = await ethers.getContractFactory("TestContract");
[owner, addr1, addr2, ...addrs] = await ethers.getSigners();
hardhatToken = await Token.deploy("test");
});
it("First test", async function () {
let total = await hardhatToken.totalSupply() // BigNumber { value: "0" }
let userBalance2 = await hardhatToken.getUserBalance(owner.address) // BigNumber { value: "9999979080649422213031" }
let userBalance = await hardhatToken.balanceOf(owner.address) // BigNumber { value: "0" }
let cBalance = await hardhatToken.getContractBalance() // BigNumber { value: "0" }
})
I think it's because a different unity (ether -> wei) but I don't know why. Can you explain me ?
Thank you
This function returns the amount of eth of the _owner.
function getUserBalance(address _owner) external view returns (uint) {
return address(_owner).balance;
}
This function returns the amount of the eth that the contract own.
function getContractBalance() public view onlyOwner returns (uint) {
return address(this).balance;
}
This function returns the amount of TOKEN that the owner has:
balanceOf(owner.address)
Related
so I have this contract
pragma solidity >=0.7.0 <0.9.0;
struct Universe{
uint256 year;
uint64[3] space;
}
contract myContract {
mapping(address => Universe) public myUni;
function setSomething(uint256 _year, uint64[3] memory _space) public {
Universe memory testUni = Universe({
year: _year,
space: _space
});
myUni[msg.sender] = testUni;
}
}
And I am currently trying to test if the array is being passed correctly with truffle:
pragma solidity >=0.7.0 <0.9.0;
const myContract = artifacts.require("./1_Storage.sol");
contract('myContract', (accounts) => {
it('checks if setSomething works', async () => {
const myContractInstance = await myContract.new();
const spaceData = [6000, 6000, 6000];
await myContractInstance.setSomething(2543,spaceData,{from: accounts[1]});
const myPassedData = (await myContractInstance.myUni(accounts[1]));
console.log(myPassedData);
console.log(spaceData);
});
});
The issue is, that I am not able to get spaceData passed into the function and I don't know why. The console.log(myPassedData); shows me only the year and when I try something like console.log(myPassedData.spaceData); it says undefined.
Thanks #sms for the link. As stated in the solidity Documentation:
If you have a public state variable of array type, then you can only
retrieve single elements of the array via the generated getter
function. This mechanism exists to avoid high gas costs when returning
an entire array.
So I had to write a Getter-Function inside of the Contract to be able to access the array:
function getUniverseArray(address _address) public view returns (uint64[3] memory) {
return myUni[_address].space;
}
I am trying the below code, elementary reentrancy example.
The current code works but transfer or send doesn't work. It reverts. What are the reasons?
Note: I chose setCaller to reenter to test the fact that updating the dirty state variable (already modified var in the same tx) takes less gas.
// SPDX-License-Identifier: Unlicensed
pragma solidity 0.8.7;
contract TestFund {
// success, if caller is itself.
address public caller;
constructor() payable {}
function getBalance() public view returns (uint) {
return address(this).balance;
}
function emptyFn(address dummy) public {}
function setCaller(address _caller) public {
caller = _caller;
}
function withdraw() external {
caller = msg.sender;
// require(payable(msg.sender).send(1 wei));
// payable(msg.sender).transfer(1 wei);
(bool success, bytes memory data) = payable(msg.sender).call{gas: 2300, value:1 wei}("");
require(success);
}
}
contract Attack {
function getBalance() public view returns (uint) {
return address(this).balance;
}
function attack(address target) external {
TestFund(target).withdraw();
}
receive() external payable {
if (getBalance() == 1 wei) {
TestFund(msg.sender).setCaller(msg.sender);
}
}
}
I'm trying to verify and submit my contract source code to etherscan using a headset, but I'm getting the following error and I don't understand how to solve it. I've read through the code and can't figure out what I'm doing wrong. Please can anyone advise?
The error that I am getting when I run:
NomicLabsHardhatPluginError: The constructor for contracts/FundMe.sol:FundMe has 1 parameters
but 0 arguments were provided instead.
heres all the code FundMe.sol code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import "#chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "./PriceConverter.sol";
error NotOwner();
contract FundMe {
using PriceConverter for uint256;
mapping(address => uint256) public addressToAmountFunded;
address[] public funders;
address public /* immutable */ i_owner;
uint256 public constant MINIMUM_USD = 50 * 10 ** 18;
AggregatorV3Interface public priceFeed;
constructor(address priceFeedAddress) {
i_owner = msg.sender;
priceFeed = AggregatorV3Interface(priceFeedAddress);
}
function fund() public payable {
require(msg.value.getConversionRate(priceFeed) >= MINIMUM_USD, "You need to spend more ETH!");
addressToAmountFunded[msg.sender] += msg.value;
funders.push(msg.sender);
}
modifier onlyOwner {
if (msg.sender != i_owner) revert NotOwner();
_;
}
function withdraw() payable onlyOwner public {
for (uint256 funderIndex=0; funderIndex < funders.length; funderIndex++){
address funder = funders[funderIndex];
addressToAmountFunded[funder] = 0;
}
funders = new address[](0);
(bool callSuccess, ) = payable(msg.sender).call{value: address(this).balance}("");
require(callSuccess, "Call failed");
}
fallback() external payable {
fund();
}
receive() external payable {
fund();
}
}
and also the 01-deploy-fund-me.js to see the code of verify
const { getNamedAccounts, deployments, network } = require("hardhat")
const { networkConfig, developmentChains } = require("../helper-hardhat-config")
const { verify } = require("../utils/verify")
module.exports = async ({ getNamedAccounts, deployments }) => {
const { deploy, log } = deployments
const { deployer } = await getNamedAccounts()
const chainId = network.config.chainId
let ethUsdPriceFeedAddress
if (chainId == 31337) {
const ethUsdAggregator = await deployments.get("MockV3Aggregator")
ethUsdPriceFeedAddress = ethUsdAggregator.address
} else {
ethUsdPriceFeedAddress = networkConfig[chainId]["ethUsdPriceFeed"]
}
log("----------------------------------------------------")
log("Deploying FundMe and waiting for confirmations...")
const fundMe = await deploy("FundMe", {
from: deployer,
args: [ethUsdPriceFeedAddress],
log: true,
// we need to wait if on a live network so we can verify properly
waitConfirmations: network.config.blockConfirmations || 1,
})
//log("----------------------------------------------------")
log(`FundMe deployed at ${fundMe.address}`)
if (
!developmentChains.includes(network.name) &&
process.env.ETHERSCAN_API_KEY
) {
await verify(fundMe.address, [ethUsdPriceFeedAddress])
}
log("----------------------------------------------------")
}
module.exports.tags = ["all", "fundme"]
Please help me!
Need help. I got the following error:
Error: VM Exception while processing transaction: reverted with reason string 'multi call failed'
at RoleMultiCall.multiCall (contracts/optional/RoleMultiCall.sol:21)
at async HardhatNode._mineBlockWithPendingTxs (/Users/azlan/projects/hardhats/dao-mix/node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:1772:23)
at async HardhatNode.mineBlock (/Users/azlan/projects/hardhats/dao-mix/node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:466:16)
at async EthModule._sendTransactionAndReturnHash (/Users/azlan/projects/hardhats/dao-mix/node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:1496:18)
at async HardhatNetworkProvider.request (/Users/azlan/projects/hardhats/dao-mix/node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:118:18)
at async EthersProviderWrapper.send (/Users/azlan/projects/hardhats/dao-mix/node_modules/#nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20)
when execute the following codes in a Hardhat task:
const targets = [timeLockContract.address, timeLockContract.address];
const encodedFunctions = [
await timeLockContract.getDataGrantProposerRole(governorContract.address),
await timeLockContract.getDataGrantExecutorRole(governorContract.address),
];
const multiCallResult = await roleMultiCall.multiCall(
targets,
encodedFunctions,
);
multi call contract :
contract RoleMultiCall {
function multiCall(
address[] calldata targets,
bytes[] calldata encodedFunctions
) external returns (bytes[] memory) {
...
for (uint256 i; i < targets.length; i++) {
(bool success, bytes memory result) = address(targets[i]).call(
encodedFunctions[i]
);
require(success, 'multi call failed');
results[i] = result;
}
return results;
}
}
contract that uses abi.encodeWithSelector:
contract GovernanceTimeLock is TimelockController {
...
function getDataGrantProposerRole(address account)
external
view
returns (bytes memory)
{
return
abi.encodeWithSelector(
this.grantRole.selector,
this.PROPOSER_ROLE,
account
);
}
function getDataGrantExecutorRole(address account) external view
returns (bytes memory)
{
//similar to function above
}
Its all here https://github.com/azizazlan/dao-mix/tree/feature/multi-call-roles
Ok. the RoleMultiCall contract must be granted the TIMELOCK_ADMIN_ROLE role.
So in the Hardhat task:
...
await timeLockContract.grant(
await timeLockContract.TIMELOCK_ADMIN_ROLE(),
roleMultiCall.address);
const multiCallResult = await roleMultiCall.multiCall(
targets,
encodedFunctions,
);
I am trying to verify my contract with arguments and I am getting this error:
Error in plugin #nomiclabs/hardhat-etherscan: The contract verification failed.
Reason: Fail - Unable to verify
I am also importing Open Zeppelin contracts ERC721Enumerable and Ownable.
Here's my NFTCollectible.sol
pragma solidity 0.8.10;
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "hardhat/console.sol";
contract NFTCollectible is ERC721Enumerable, Ownable {
using Strings for uint256;
string public baseURI;
string public baseExtension = ".json";
uint256 public cost = 0.08 ether;
uint256 public maxSupply = 5000;
uint256 public maxMintAmount = 25;
mapping(address => uint256) public addressMintedBalance;
constructor(
string memory _name,
string memory _symbol,
string memory _initBaseURI,
string memory _initNotRevealedUri
) ERC721(_name, _symbol) {
setBaseURI(_initBaseURI);
setNotRevealedURI(_initNotRevealedUri);
}
function _baseURI() internal view virtual override returns (string memory) {
return baseURI;
}
function mint(uint256 _mintAmount) public payable {
require(!paused, "the contract is paused");
uint256 supply = totalSupply();
require(_mintAmount > 0, "need to mint at least 1 NFT");
}
function walletOfOwner(address _owner)
public
view
returns (uint256[] memory)
{
uint256 ownerTokenCount = balanceOf(_owner);
uint256[] memory tokenIds = new uint256[](ownerTokenCount);
for (uint256 i; i < ownerTokenCount; i++) {
tokenIds[i] = tokenOfOwnerByIndex(_owner, i);
}
return tokenIds;
}
function tokenURI(uint256 tokenId)
public
view
virtual
override
returns (string memory)
{
require(
_exists(tokenId),
"ERC721Metadata: URI query for nonexistent token"
);
string memory currentBaseURI = _baseURI();
return
bytes(currentBaseURI).length > 0
? string(
abi.encodePacked(
currentBaseURI,
tokenId.toString(),
baseExtension
)
)
: "";
}
function setCost(uint256 _newCost) public onlyOwner {
cost = _newCost;
}
function setBaseURI(string memory _newBaseURI) public onlyOwner {
baseURI = _newBaseURI;
}
function setBaseExtension(string memory _newBaseExtension)
public
onlyOwner
{
baseExtension = _newBaseExtension;
}
function withdraw() public payable onlyOwner {
(bool me, ) = payable(owner())
.call{value: address(this).balance}("");
require(me);
}
}
Here's my deploy.js
const main = async () => {
const nftContractFactory = await hre.ethers.getContractFactory('NFTCollectible');
const nftContract = await nftContractFactory.deploy(
"NFTCollectible",
"NFTC",
"ipfs://CID",
"https://www.example.com"
);
await nftContract.deployed();
console.log("Contract deployed to:", nftContract.address);
};
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.log(error);
process.exit(1);
}
};
runMain();
Here's my hardhat.config
require('#nomiclabs/hardhat-waffle');
require('#nomiclabs/hardhat-etherscan');
require('dotenv').config();
module.exports = {
solidity: '0.8.10',
networks: {
rinkeby: {
url: process.env.STAGING_ALCHEMY_KEY,
accounts: [process.env.PRIVATE_KEY],
},
mainnet: {
chainId: 1,
url: process.env.PROD_ALCHEMY_KEY,
accounts: [process.env.PRIVATE_KEY],
gasPrice: 3000000
},
},
etherscan: {
apiKey: process.env.ETHERSCAN_KEY
}
};
I realize Hardhat does not support 0.8.10+ compiler version, but no other versions work either. Same error.
You need to pass in the constructor into the command line.
hh verify --network mainnet DEPLOYED_CONTRACT_ADDRESS "Constructor argument 1"
Here's the documentation.
https://hardhat.org/plugins/nomiclabs-hardhat-etherscan.html
You have this error because you are not using the same arguments that you used during the deployment, be sure to use the same arguments at deployment as at verification
What worked for me is changing:
etherscan: {
apiKey: process.env.ETHERSCAN_KEY
}
to:
etherscan: {
apiKey: {
rinkeby:"ETHERSCAN API KEY HERE",
}
}
SOLVED
This isn't really an answer, but my solve was to use both Remix and Hardhat, the latter via VSCode. Basically, deploy via Remix and verify through Hardhat.
Because I'm using libraries, I need to verify every file, obviously. The degen way of pasting every Open Zeppelin file...I don't recommend it. I tried and still got it wrong.
Suspicion: I was not creating a transaction in my deploy script, which is weird because my params seem correct. In any event...
My issue is resolved by simply adding my own proxy config in the "hardhat.config.js" file:
// set proxy
const { ProxyAgent, setGlobalDispatcher } = require("undici");
const proxyAgent = new ProxyAgent('http://127.0.0.1:7890'); // change to yours
setGlobalDispatcher(proxyAgent);
I got success finally:
I just used the docs here and using the npx hardhat --network xxxx verify xxxx worked for me. One more thing is be patient maybe you need to execute this after a few block since the Smart contract deployment.