ERC721: invalid token ID when trying to connect two smart contracts - blockchain

So I have this contract here named MyToken
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
contract MyToken is ERC721, Ownable {
constructor() ERC721("MyToken", "MTK") {}
function safeMint(address to, uint256 tokenId) public onlyOwner {
_safeMint(to, tokenId);
}
}
and I am importing it from another contract named Marketplace
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "./MyToken.sol";
contract Marketplace {
MyToken token= new MyToken();
constructor() {}
function sell(address _address, uint256 tokenId) public {
require(token.ownerOf(tokenId) == msg.sender, "Unauthorized.");
require(_address != address(0));
}
}
And I am trying to do a unit test:
const { expect } = require("chai");
const { ethers } = require("hardhat");
it("should sell the minted token", async function() {
const [owner] = await ethers.getSigners();
const Market = await ethers.getContractFactory("Marketplace");
const marketContract = await Market.deploy();
const Token = await ethers.getContractFactory("MyToken");
const tokenContract = await Token.deploy();
await tokenContract.safeMint(owner.address, 1);
//IT FAILS THE CODE BELOW
await marketContract.sell(tokenContract.address, 1);
})
It seems that it cannot read the token with the ID of 1 when I have minted it with the tokenContract. Then it gives me error that the token ID is invalid because of the require I have provided in the Marketplace. Please help me. Thanks

The issue is that you create a new Token Contract internal to your market, but you don't mint from that one"
// this is the error
MyToken token= new MyToken();
instead take the address for the token in the constructor.
contract Marketplace {
// this is the error
MyToken token= new MyToken();
constructor(MyToken _token) {
token = _token;
}
}
Note: you should additionally probably consider using Owner.sol and adding authorization

Related

transaction fails when I call getRandomNumber() function from chainlink VRF v1

I am using chainlink VRF v1 to get a random number. I am using ethers.js to call the getRandomNumber() function but it always fails with this message: Error: transaction failed [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ]
I have enought LINK in my contract so that is not the reason for this. Is there any other possible or anything wrong with my code?
my smart contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
import "#chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
contract VRFConsumer is VRFConsumerBase {
bytes32 keyHash;
uint256 requiredFee;
uint256 public randomResult;
constructor()
VRFConsumerBase(
0x844ECf0B33EB65e1EC34AEa0d082D39879169890,
0xa36085F69e2889c224210F603D836748e7dC0088
)
{
keyHash = 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4;
requiredFee = 0.1 * 10**18;
}
function getRandomNumber() public returns (bytes32 requestId) {
require(
LINK.balanceOf(address(this)) >= requiredFee,
"Not enough LINK - fill contract with faucet"
);
return requestRandomness(keyHash, requiredFee);
}
function fulfillRandomness(
bytes32, /*requestId*/
uint256 randomness
) internal override {
randomResult = randomness;
}
}
my frontend code:
const provider: ethers.providers.Web3Provider = new ethers.providers.Web3Provider((window as any).ethereum;
);
const signer: ethers.providers.JsonRpcSigner = provider.getSigner();
const vrfConsumer = new ethers.Contract(
this.address,
vrfConsumerABI,
provider
);
console.log("Start");
const vrfConsumerWithSigner = vrfConsumer.connect(signer);
const tx = await vrfConsumerWithSigner.getRandomNumber({
gasPrice: 3000000000,
gasLimit: 2000000,
});
await tx.wait();
const result: BigNumber = await vrfConsumer.randomResult();
console.log(result.toNumber());
console.log("done");
I suggest you to check some functions in Chainlink hardhat-starter-kit
helper-functions.js
tasks\random-number-consumer\request-random-number.js
tasks\random-number-consumer\read-random-number.js

SyntaxError: Unexpected token o in JSON at position 1. In Solidity version ^0.8.7

Hey Guys, I'm using latest solidity version 0.8.7. I'm getting this SyntaxError: Unexpected token o in JSON at position 1. Please help me regarding this problem. When I run npm run test command, it gives me this error. I really need help to get rid of this issue. That's why I'm not able to proceed further in learning solidity. Thanks a lot
**Lottery.sol File - **
pragma solidity ^0.8.7; // latest solidity version...
contract Lottery
{
address public manager;
address[] public players;
constructor()
{
manager = msg.sender;
}
function enter() public payable
{
require(msg.value > .01 ether);
players.push(msg.sender);
}
function random() private view returns (uint256)
{
return
uint256(keccak256(abi.encodePacked(block.difficulty, block.timestamp, players)));
}
function pickWinner() public restricted
{
require(msg.sender == manager);
uint256 index = random() % players.length;
uint256 amount = address(this).balance;
payable(players[index]).transfer(amount);
players = new address[](0);
}
modifier restricted()
{
require(msg.sender == manager);
_;
}
function getPlayers() public view returns (address[] memory)
{
return players;
}
}
Compile.js File -
const path = require("path");
const fs = require("fs");
const solc = require("solc");
const lotteryPath = path.resolve(__dirname, 'contracts', 'Lottery.sol');
const source = fs.readFileSync(lotteryPath, "utf8");
var input = {
language: 'Solidity',
sources: {
'lottery.sol' : {
content: source
}
},
settings: {
outputSelection: {
'*': {
'*': [ '*' ]
}
}
}
};
const output = JSON.parse(solc.compile(JSON.stringify(input))); // error on this line probably
const interface = output.contracts['lottery.sol'].lotteryPath.abi;
const bytecode = output.contracts['lottery.sol'].lotteryPath.evm.bytecode.object;
module.exports = {
interface,
bytecode,
};
lottery.test.js File
const assert = require("assert");
const ganache = require("ganache-cli");
const Web3 = require("web3");
const web3 = new Web3(ganache.provider());
const { interface, bytecode } = require("../compile");
let lottery;
let accounts;
beforeEach(async () => {
accounts = await web3.eth.getAccounts();
lottery = await new web3.eth.Contract(JSON.parse(interface)) // error on this line probably
.deploy({ data: bytecode })
.send({ from: accounts[0], gas: '1000000' });
});
describe("Lottery Contract", () => {
it("deploys a contract", () => {
assert.ok(lottery.options.address);
});
});
deploy.js File -
const HDWalletProvider = require("#truffle/hdwallet-provider");
const Web3 = require("web3");
const { interface, bytecode } = require("./compile");
const provider = new HDWalletProvider(
"*******************************************",
"https://rinkeby.infura.io/v3/********************"
);
const web3 = new Web3(provider);
const deploy = async () => {
const accounts = await web3.eth.getAccounts();
console.log("Attempting to deploy from accoutns", accounts[0]);
const result = await new web3.eth.Contract(JSON.parse(interface))
.deploy({ data: bytecode})
.send({ gas: '1000000', from: accounts[0] });
console.log("Contract deployed to", result.options.address);
};
Follow these steps.
Step 1: Check the solidity compiler version
Go to your package.json file. Under the dependencies object you will find the solc version.
Here make sure the solidity version is the same that you used in your Lottery.sol file.
If the version is not the same then please install the right version using npm
In my case, I am using ^0.8.8 in my solidity file. So I run the following command:
npm install solc#0.8.8
Step 2: Update your lottery.test.js file
In your lottery.test.js file update this line
lottery = await new web3.eth.Contract(JSON.parse(interface))
to this
lottery = await new web3.eth.Contract(interface)
Step 3: Update your deploy.js file
In your deploy.js file update this line
const result = await new web3.eth.Contract(JSON.parse(interface))
to this
const result = await new web3.eth.Contract(interface)
Also, it's a good practice to add your deployment code into a try/catch block like this:
try {
const accounts = await web3.eth.getAccounts();
console.log("Attempting to deploy from accoutns", accounts[0]);
const result = await new web3.eth.Contract(interface)
.deploy({ data: bytecode})
.send({ gas: '1000000', from: accounts[0] });
console.log("Contract deployed to", result.options.address);
} catch(error) {
console.log(error);
}
Note: Finally ensure in your deployment account you have enough ethers to test with. If you don't then get some ethers using faucets

Verify/Publish Smart Contract on Etherscan Rinkeby

I am attempting to Verify and Publish a smart contract that I have deployed to the rinkeby network using hardhat and hardhat-etherscan. When I am running the verify script I am getting an error.
I run the following commands
npx hardhat clean
npx hardhat verify --network rinkeby 0xDDeE39Ae632760906d273B450493405Dc3C455Fe "ipfs://QmX6MjxS5NsEFGe9WtKCskf5fhuifFvZ9Xi12tTBYPjEiH"
After running the script above I get the below error.
Compiling 17 files with 0.8.4
Compilation finished successfully
Compiling 1 file with 0.8.4
Successfully submitted source code for contract
contracts/NFTCollectible.sol:NFTCollectible at 0xDDeE39Ae632760906d273B450493405Dc3C455Fe
for verification on Etherscan. Waiting for verification result...
We tried verifying your contract NFTCollectible without including any unrelated one, but it failed.
Trying again with the full solc input used to compile and deploy it.
This means that unrelated contracts may be displayed on Etherscan...
Successfully submitted source code for contract
contracts/NFTCollectible.sol:NFTCollectible at 0xDDeE39Ae632760906d273B450493405Dc3C455Fe
for verification on Etherscan. Waiting for verification result...
Error in plugin #nomiclabs/hardhat-etherscan: The contract verification failed.
Reason: Fail - Unable to verify
hardhat.config.js
require("#nomiclabs/hardhat-waffle");
require("#nomiclabs/hardhat-etherscan");
require('dotenv').config();
const { API_URL, PRIVATE_KEY, ETHERSCAN_API } = process.env;
// This is a sample Hardhat task. To learn how to create your own go to
// https://hardhat.org/guides/create-task.html
task("accounts", "Prints the list of accounts", async (taskArgs, hre) => {
const accounts = await hre.ethers.getSigners();
for (const account of accounts) {
console.log(account.address);
}
});
// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more
/**
* #type import('hardhat/config').HardhatUserConfig
*/
module.exports = {
solidity: "0.8.4",
defaultNetwork: "rinkeby",
networks: {
rinkeby: {
url: API_URL,
accounts: [PRIVATE_KEY]
}
},
etherscan: {
apiKey: ETHERSCAN_API
}
};
My smart contract included several imports from openzepplin.
//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";
contract NFTCollectible is ERC721Enumerable, Ownable {
using SafeMath for uint256;
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
uint256 public constant MAX_SUPPLY = 100;
uint256 public constant PRICE = 0.01 ether;
uint256 public constant MAX_PER_MINT = 5;
string public baseTokenURI;
constructor(string memory baseURI) ERC721("NFT Collectible", "NFTC") {
setBaseURI(baseURI);
}
function reserveNFTs() public onlyOwner {
uint256 totalMinted = _tokenIds.current();
require(totalMinted.add(10) < MAX_SUPPLY, "Not enough NFTs");
for (uint256 i = 0; i < 10; i++) {
_mintSingleNFT();
}
}
function _baseURI() internal view virtual override returns (string memory) {
return baseTokenURI;
}
function setBaseURI(string memory _baseTokenURI) public onlyOwner {
baseTokenURI = _baseTokenURI;
}
function mintNFTs(uint256 _count) public payable {
uint256 totalMinted = _tokenIds.current();
require(totalMinted.add(_count) <= MAX_SUPPLY, "Not enough NFTs!");
require(
_count > 0 && _count <= MAX_PER_MINT,
"Cannot mint specified number of NFTs."
);
require(
msg.value >= PRICE.mul(_count),
"Not enough ether to purchase NFTs."
);
for (uint256 i = 0; i < _count; i++) {
_mintSingleNFT();
}
}
function _mintSingleNFT() private {
uint256 newTokenID = _tokenIds.current();
_safeMint(msg.sender, newTokenID);
_tokenIds.increment();
}
function tokensOfOwner(address _owner)
external
view
returns (uint256[] memory)
{
uint256 tokenCount = balanceOf(_owner);
uint256[] memory tokensId = new uint256[](tokenCount);
for (uint256 i = 0; i < tokenCount; i++) {
tokensId[i] = tokenOfOwnerByIndex(_owner, i);
}
return tokensId;
}
function withdraw() public payable onlyOwner {
uint256 balance = address(this).balance;
require(balance > 0, "No ether left to withdraw");
(bool success, ) = (msg.sender).call{value: balance}("");
require(success, "Transfer failed.");
}
}
I just had this problem and solved it by realizing that my constructor arguments did not match with what I originally deployed the contract with. For you it is possible this:
npx hardhat verify --network rinkeby 0xDDeE39Ae632760906d273B450493405Dc3C455Fe "ipfs://QmX6MjxS5NsEFGe9WtKCskf5fhuifFvZ9Xi12tTBYPjEiH"
should actually be:
npx hardhat verify --network rinkeby 0xDDeE39Ae632760906d273B450493405Dc3C455Fe "QmX6MjxS5NsEFGe9WtKCskf5fhuifFvZ9Xi12tTBYPjEiH"
with the ipfs:// removed if you did not originally include it when you initially deployed the contract.
I would redeploy it and double check the parameters used when deploying are identical to the ones used when verifying.

How to transfer ERC1155 token using web3js?

I am trying to transfer ERC1155 tokens to another account. I have deployed the contract and have put down my contract code below.
The problem I am facing is I get the below error when I call getMyToken function from my frontend web3js code.
{code: -32603, message: 'execution reverted: ERC1155: caller is not owner nor approved', data: {…}}
Not sure what is happening. I am calling the function as below from frontend. The isApproved function is returning true.
const selectedAccountIsApproved = await monkeysContract.methods.isApproved(selectedAccount).call();
console.log('IS APPROVED RESULT: ', selectedAccountIsApproved);
if(selectedAccountIsApproved) {
const result = await monkeysContract.methods.mintMyMonkey(selectedAccount, 0).call();
console.log('Transfer Result: ', result);
} else {
console.log('Account not approved by owner for transfers');
}
NOTE:
I have called the setApprovalForAll method and approved the receiver account.
I am able to call isApprovedForAll and verify that the account is approved.
I am able to transfer tokens to the receiver through Etherscan contract interface.
Contract Code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "#openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
contract Monkeys is ERC1155, Ownable {
uint256 public constant CC1 = 0;
uint256 public constant CC2 = 1;
mapping (uint256 => string) private _uris;
constructor() public ERC1155("https://game.example/api/item/{id}.json") {
_mint(msg.sender, CC1, 1000, "");
_mint(msg.sender, CC2, 1000, "");
}
function uri(uint256 tokenId) override public view returns (string memory) {
return(_uris[tokenId]);
}
function setTokenUri(uint256 id, string memory url) public onlyOwner {
require(bytes(_uris[id]).length == 0, "Cannot set uri twice");
_uris[id] = url;
}
function transfer(address from, address to, uint256 id, uint256 amount, bytes memory data) public {
safeTransferFrom(from, to, id, amount, data);
}
function isApproved(address user) public view virtual returns (bool) {
return isApprovedForAll(owner(), user);
}
function getMyToken(address to, uint256 id) public {
transfer(owner(), to, id, 1, 'test');
}
}

Why am I receiving the following Chainlink error: cannot estimate gas

I am trying to follow the Chainlink VRF tutorial found here: https://docs.chain.link/docs/intermediates-tutorial/ with hardhat and am running into this issue when calling the rollDice function:
Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"reason":"cannot estimate gas; transaction may fail or may require manual gas limit","code":"UNPREDICTABLE_GAS_LIMIT","method":"estimateGas","transaction":{"from":"0x014Da1D627E6ceB555975F09D26B048644382Ac6","maxPriorityFeePerGas":{"type":"BigNumber","hex":"0x9502f900"},"maxFeePerGas":{"type":"BigNumber","hex":"0x9502f90e"},"to":"0x5887946875A01D1BB79d6Fb357BceeA5A0096D2e","data":"0xdd02d9e5000000000000000000000000014da1d627e6ceb555975f09d26b048644382ac6","type":2,"accessList":null}}, tx={"data":"0xdd02d9e5000000000000000000000000014da1d627e6ceb555975f09d26b048644382ac6","to":{},"from":"0x014Da1D627E6ceB555975F09D26B048644382Ac6","type":2,"maxFeePerGas":{"type":"BigNumber","hex":"0x9502f90e"},"maxPriorityFeePerGas":{"type":"BigNumber","hex":"0x9502f900"},"nonce":{},"gasLimit":{},"chainId":{}}, code=UNPREDICTABLE_GAS_LIMIT, version=abstract-signer/5.5.0)
at Logger.makeError (/Users/matt/Desktop/hardhat/randomDay/node_modules/#ethersproject/logger/src.ts/index.ts:225:28)
at Logger.throwError (/Users/matt/Desktop/hardhat/randomDay/node_modules/#ethersproject/logger/src.ts/index.ts:237:20)
at /Users/matt/Desktop/hardhat/randomDay/node_modules/#ethersproject/abstract-signer/src.ts/index.ts:301:31
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Promise.all (index 7)
I am able to deploy to the Kovan testnet, I was able to verify the contract, and I have sent the contract LINK tokens, but am still running into the issue. The contract can be viewed here: https://kovan.etherscan.io/address/0x7b72d80670512c87605ab8ac7e6113fda9c57de4#code
I am using version 0.8 of the Chainlink Contracts.
RandomDay.sol
pragma solidity ^0.8.9;
import "#chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
contract RandomDay is VRFConsumerBase {
uint256 private constant ROLL_IN_PROGRESS = 42;
bytes32 private s_keyHash;
uint256 private s_fee;
mapping(bytes32 => address) private s_rollers;
mapping(address => uint256) private s_results;
event DiceRolled(bytes32 indexed requestId, address indexed roller);
event DiceLanded(bytes32 indexed requestId, uint256 indexed result);
constructor(address vrfCoordinator, address link, bytes32 keyHash, uint256 fee) VRFConsumerBase(vrfCoordinator, link) {
s_keyHash = keyHash;
s_fee = fee;
}
function rollDice (address roller) public returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) >= s_fee, "Not enough LINK to pay fee");
require(s_results[roller] == 0, "Already rolled");
requestId = requestRandomness(s_keyHash, s_fee);
s_rollers[requestId] = roller;
s_results[roller] = ROLL_IN_PROGRESS;
emit DiceRolled(requestId, roller);
return requestId;
}
function fulfillRandomness (bytes32 requestId, uint256 randomness) internal override {
uint256 dayOfWeek = (randomness % 7) + 1;
s_results[s_rollers[requestId]] = dayOfWeek;
emit DiceLanded(requestId, dayOfWeek);
}
function weekday (address player) public view returns (string memory) {
require(s_results[player] != 0, "Dice not rolled");
require(s_results[player] != ROLL_IN_PROGRESS, "Roll in progress");
return getWeekdayName(s_results[player]);
}
function getWeekdayName (uint256 id) private pure returns (string memory) {
string[7] memory weekdays = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
return weekdays[id - 1];
}
}
hardhat.config.js
/**
* #type import('hardhat/config').HardhatUserConfig
*/
require("#nomiclabs/hardhat-waffle")
require("#nomiclabs/hardhat-etherscan")
const ALCHEMY_API_KEY = "*************************";
const ROPSTEN_PRIVATE_KEY = "*********************";
module.exports = {
solidity: "0.8.9",
networks: {
kovan: {
url: `https://eth-kovan.alchemyapi.io/v2/${ALCHEMY_API_KEY}`,
accounts: [`0x${ROPSTEN_PRIVATE_KEY}`],
gas: 2700000000,
maxFeePerGas: 30000000000,
}
},
etherscan: {
// Your API key for Etherscan
// Obtain one at https://etherscan.io/
apiKey: "****************************"
}
};
deploy.js
const { ethers } = require("hardhat");
async function main() {
const [deployer] = await ethers.getSigners();
console.log("Deploying contracts with the account:", deployer.address);
console.log("Account balance:", (await deployer.getBalance()).toString());
const Token = await ethers.getContractFactory("RandomDay");
const token = await Token.deploy("0xa36085F69e2889c224210F603D836748e7dC0088", "0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9", "0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4", "100000000000000000");
console.log("Token address:", token.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
quickRun.js
var ethers = require('ethers');
var provider = ethers.providers.getDefaultProvider('kovan');
var address = '0x7b72d80670512c87605aB8aC7E6113Fda9c57de4';
var abi = [{"inputs":[{"internalType":"address","name":"vrfCoordinator","type":"address"},{"internalType":"address","name":"link","type":"address"},{"internalType":"bytes32","name":"keyHash","type":"bytes32"},{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"result","type":"uint256"}],"name":"DiceLanded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"roller","type":"address"}],"name":"DiceRolled","type":"event"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"uint256","name":"randomness","type":"uint256"}],"name":"rawFulfillRandomness","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"roller","type":"address"}],"name":"rollDice","outputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"}],"name":"weekday","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}];
var privateKey = '*******************************';
var wallet = new ethers.Wallet(privateKey, provider);
var contract = new ethers.Contract(address, abi, wallet);
var sendPromise = contract.rollDice('0x014Da1D627E6ceB555975F09D26B048644382Ac6');
sendPromise.then(function(transaction){
console.log(transaction);
});
I believe the addresses are off:
Constructor Arguments of your contract:
-----Decoded View---------------
Arg [0] : vrfCoordinator (address): 0xa36085f69e2889c224210f603d836748e7dc0088
Arg [1] : link (address): 0xdd3782915140c8f3b190b5d67eac6dc5760c46e9
Arg [2] : keyHash (bytes32): 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4
Arg [3] : fee (uint256): 100000000000000000
Via Chainlinks Docs:
LINK 0xa36085F69e2889c224210F603D836748e7dC0088
VRF Coordinator 0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9
Key Hash 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4
Fee 0.1 LINK
Switched Link and VRF are probably the culprit.
9 out of 10 is because you passed something wrong in the constructor or something in the contructor is not initialized propertly. this kind of things aren't detected by compiler.