TypeError: Member "length" not found or not visible after argument-dependent lookup in mapping(address => mapping(uint256 => uint256)) - ethereum

I am new in this smart contract area. So what I am learning right now is that when we are deploying a new contract then the data from the old contract will not be automatically moved to the new contract and we need to create a migration function by ourselves to migrate the data from old contract to the new contract. I tried to create the migration function by taking some reference from another post. But when I try to compile the contract, I find this error
TypeError: Member "length" not found or not visible after argument-dependent lookup in mapping(address => mapping(uint256 => uint256)).
This error happens inside this function
function transferData(address payable newContractAddress) public {
// Reference the new contract
NFTMinter newContract = NFTMinter(newContractAddress);
// Transfer each balance
// ERROR HAPPEN HERE
for (uint256 i = 0; i < _balances.length; i++) {
newContract.setBalance(_balances[i], _balances[_balances[i]]);
}
// Transfer each tokenIds array
// ERROR HAPPEN HERE
for (uint256 i = 0; i < _tokenIds.length; i++) {
for (uint256 j = 0; j < _tokenIds[i].length; i++) {
newContract.addTokenId(_tokenIds[i], _tokenIds[i][j]);
}
}
// Transfer each token price
// ERROR HAPPEN HERE
for (uint256 i = 0; i < tokenPrice.length; i++) {
newContract.setTokenPrice(tokenPrice[i], tokenPrice[tokenPrice[i]]);
}
}
This is how my whole contract looks like
contract NFTMinter is ERC1155 {
constructor() ERC1155("https://raw.githubusercontent.com/noopmood/TutorialNFTInGo/main/metadata/{id}.json") payable {}
// Define the mapping of addresses to balances
mapping(address => mapping(uint256 => uint256)) public _balances;
// Define the mapping of address to tokenIds owned
mapping(address => uint256[]) public _tokenIds;
// Define the mapping of tokenId to price
mapping(uint256 => uint256) public tokenPrice;
struct Token {
uint256 tokenId;
uint256 balance;
}
// Mints new tokens and sets the price for each token.
function mintAddress(uint256 tokenId, uint256 amount, address addr, uint256 price) public{
_mint(addr, tokenId, amount, "");
// Update the balance of the recipient
_balances[addr][tokenId] += amount;
// Add the tokenId to the address
_tokenIds[addr].push(tokenId);
// Set the price of the token
tokenPrice[tokenId] = price;
}
// Get all tokenIds from its owner address
function getTokenIdsByAddress(address addr) public view returns (uint[] memory) {
return _tokenIds[addr];
}
// Get the tokenIds along with its corresponding balances/amount
function getAllTokenByAddress(address holder) public view returns (Token[] memory) {
Token[] memory result = new Token[](_tokenIds[holder].length);
for (uint i = 0; i < _tokenIds[holder].length; i++) {
result[i].tokenId = _tokenIds[holder][i];
result[i].balance = _balances[holder][_tokenIds[holder][i]];
}
return result;
}
function transferData(address payable newContractAddress) public {
// Reference the new contract
NFTMinter newContract = NFTMinter(newContractAddress);
// Transfer each balance
for (uint256 i = 0; i < _balances.length; i++) {
newContract.setBalance(_balances[i], _balances[_balances[i]]);
}
// Transfer each tokenIds array
for (uint256 i = 0; i < _tokenIds.length; i++) {
for (uint256 j = 0; j < _tokenIds[i].length; i++) {
newContract.addTokenId(_tokenIds[i], _tokenIds[i][j]);
}
}
// Transfer each token price
for (uint256 i = 0; i < tokenPrice.length; i++) {
newContract.setTokenPrice(tokenPrice[i], tokenPrice[tokenPrice[i]]);
}
}
function setBalance(address addr, uint256 balance) public {
_balances[addr] = balance;
}
function addTokenId(address addr, uint256 tokenId) public {
_tokenIds[addr].push(tokenId);
}
function setTokenPrice(uint256 tokenId, uint256 price) public {
tokenPrice[tokenId] = price;
}
}
Can anyone help me on figuring out this issue so I am able to compile the contract and able to migrate the data from my old to new contract?

As the error state, there's no length attribute for the map type. Based on the solidity document, there's no way to iterate through the map items.
You need to maintain an array of the address separately in order to loop through it.
Besides that, this block of code is wrong:
// Transfer each balance
for (uint256 i = 0; i < _balances.length; i++) {
newContract.setBalance(_balances[i], _balances[_balances[i]]);
}
By the _balances[i], I guess you expect to receive the address of wallet. But this actually returns the balance at address <i>. Because i is the index in this case, so _balances[i] returns 0 IIRC.
https://docs.soliditylang.org/en/v0.8.18/types.html#iterable-mappings

Related

Insufficient balance when transferring token from another address, after migrating the data from old contract to new contract

I create a migration data function to transfer the data from old contract to the new one, in case we need to update the contract. The function is working properly, I have checked the all the data has been moved to the new contract. But when I run the transfer function, it said that Reason provided by the contract: "ERC1155: insufficient balance for transfer".
migrateData function
// Define the mapping of addresses to balances
mapping(address => mapping(uint256 => uint256)) public _balances;
// Define the mapping of address to tokenIds owned
mapping(address => uint256[]) public _tokenIds;
// Define the mapping of tokenId to price
mapping(uint256 => uint256) public _tokenPrice;
address[] public _ownerAddresses;
function migrateData(address _oldContract) public payable {
NFTMinter oldContract = NFTMinter(_oldContract);
address[] memory allAddresses = oldContract.getAllAddresses();
for (uint i = 0; i < allAddresses.length; i++) {
address holder = allAddresses[i];
_ownerAddresses.push(holder);
uint256[] memory tokenIds = oldContract.getTokenIdsByAddress(holder);
for (uint j = 0; j < tokenIds.length; j++) {
uint256 tokenId = tokenIds[j];
_balances[holder][tokenId] += oldContract.getBalanceOf(holder, tokenId);
_tokenIds[holder] = oldContract.getTokenIdsByAddress(holder);
_tokenPrice[tokenId] = oldContract.getTokenPrice(tokenId);
}
}
}
transfer function
// Transfers the tokens from one address to another.
function transfer(address addr, uint256 tokenId, uint256 amount) public {
require(_balances[msg.sender][tokenId] >= amount, "Not enough balance");
// Transfer the token
_safeTransferFrom(msg.sender, addr, tokenId, amount, "");
// Update the sender's balance
_balances[msg.sender][tokenId] -= amount;
// Update the recipient's balance
_balances[addr][tokenId] += amount;
// Add the tokenId to the address
_tokenIds[addr].push(tokenId);
// Set the price of the token
_tokenPrice[tokenId] = _tokenPrice[tokenId];
}
I have make sure to check the amount of the token and it has the corrected amount from where we left in oldContract.
Is there any extra step I have to do first to make the data that I migrate from old contract to be usable in new contract?

DeclarationError: Undeclared identifier. "..." is not visible at this point

I am practising this tutorial in Remix IDE - https://www.youtube.com/watch?v=_aXumgdpnPU
I saw in the Chainlink documentation that their Randomness VRF code has been changed since the development of the video.
I started replacing the parts and trying to deploy the class via Remix but it gives an error which I am not sure how to fix.
Would you be able to check what I have as code and I'll send a screenshot of the error?
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;
import "#chainlink/contracts/src/v0.8/ConfirmedOwner.sol";
import "#chainlink/contracts/src/v0.8/VRFV2WrapperConsumerBase.sol";
contract Lottery is
VRFV2WrapperConsumerBase,
ConfirmedOwner
{
address public owner;
address payable[] public players;
uint public lotteryId;
mapping (uint => address payable) public lotteryHistory;
event RequestSent(uint256 requestId, uint32 numWords);
event RequestFulfilled(
uint256 requestId,
uint256[] randomWords,
uint256 payment
);
struct RequestStatus {
uint256 paid; // amount paid in link
bool fulfilled; // whether the request has been successfully fulfilled
uint256[] randomWords;
}
mapping(uint256 => RequestStatus)
public s_requests; /* requestId --> requestStatus */
// past requests Id.
uint256[] public requestIds;
uint256 public lastRequestId;
// Depends on the number of requested values that you want sent to the
// fulfillRandomWords() function. Test and adjust
// this limit based on the network that you select, the size of the request,
// and the processing of the callback request in the fulfillRandomWords()
// function.
uint32 callbackGasLimit = 100000;
// The default is 3, but you can set this higher.
uint16 requestConfirmations = 3;
// For this example, retrieve 2 random values in one request.
// Cannot exceed VRFV2Wrapper.getConfig().maxNumWords.
uint32 numWords = 2;
// Address LINK - hardcoded for Goerli
address linkAddress = 0x326C977E6efc84E512bB9C30f76E30c160eD06FB;
// address WRAPPER - hardcoded for Goerli
address wrapperAddress = 0x708701a1DfF4f478de54383E49a627eD4852C816;
constructor()
ConfirmedOwner(msg.sender)
VRFV2WrapperConsumerBase(linkAddress, wrapperAddress)
{
owner = msg.sender;
lotteryId = 1;
}
function requestRandomWords()
external
onlyOwner
returns (uint256 requestId)
{
requestId = requestRandomness(
callbackGasLimit,
requestConfirmations,
numWords
);
s_requests[requestId] = RequestStatus({
paid: VRF_V2_WRAPPER.calculateRequestPrice(callbackGasLimit),
randomWords: new uint256[](0),
fulfilled: false
});
requestIds.push(requestId);
lastRequestId = requestId;
emit RequestSent(requestId, numWords);
return requestId;
}
function fulfillRandomWords(
uint256 _requestId,
uint256[] memory _randomWords
) internal override {
require(s_requests[_requestId].paid > 0, "request not found");
s_requests[_requestId].fulfilled = true;
s_requests[_requestId].randomWords = _randomWords;
emit RequestFulfilled(
_requestId,
_randomWords,
s_requests[_requestId].paid
);
payWinner();
}
function getRequestStatus(
uint256 _requestId
)
external
view
returns (uint256 paid, bool fulfilled, uint256[] memory randomWords)
{
require(s_requests[_requestId].paid > 0, "request not found");
RequestStatus memory request = s_requests[_requestId];
return (request.paid, request.fulfilled, request.randomWords);
}
/**
* Allow withdraw of Link tokens from the contract
*/
function withdrawLink() public onlyOwner {
LinkTokenInterface link = LinkTokenInterface(linkAddress);
require(
link.transfer(msg.sender, link.balanceOf(address(this))),
"Unable to transfer"
);
}
function getWinnerByLottery(uint lottery) public view returns (address payable) {
return lotteryHistory[lottery];
}
function getBalance() public view returns (uint) {
return address(this).balance;
}
function getPlayers() public view returns (address payable[] memory) {
return players;
}
function enter() public payable {
require(msg.value > .01 ether);
// address of player entering lottery
players.push(payable(msg.sender));
}
//function getRandomNumber() public view returns (uint) {
//return uint(keccak256(abi.encodePacked(owner, block.timestamp)));
//}
function pickWinner() public onlyowner {
requestRandomWords;
}
function payWinner() public {
uint index = lastRequestId % players.length;
players[index].transfer(address(this).balance);
lotteryHistory[lotteryId] = players[index];
lotteryId++;
// reset the state of the contract
players = new address payable[](0);
}
modifier onlyowner() {
require(msg.sender == owner);
_;
}
}
enter image description here

How can I sell to my own nft market with my own crypto token

My goal is to sell nfts that can be bought with my own cryptocurrency on my market. For this, I access my own token using the IERC20 interface within my market contract. But I'm not that good at solidity. If I come to the plain. How do I get permission to shop with the BVC token (my token) in the user's wallet when the buy button is clicked on my website and I make this payment.
THIS MARKET.sol CODE
// SPDX-License-Identifier: MIT LICENSE
pragma solidity ^0.8.9;
import "#openzeppelin/contracts/utils/Counters.sol";
import "#openzeppelin/contracts/security/ReentrancyGuard.sol";
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/token/ERC20/IERC20.sol";
contract Market is ReentrancyGuard, Ownable {
struct TokenInfo{
IERC20 paytoken;
uint256 listingFee;
uint256 mintingFee;
uint256 price;
}
using Counters for Counters.Counter;
Counters.Counter private _itemIds;
Counters.Counter private _itemsSold;
IERC20 public paytoken;
TokenInfo[] public AllowedCrypto;
address payable holder;
//uint256 listingFee = 0.0025 ether;
//uint256 mintingFee = 0.0075 ether;
constructor() {
holder = payable(msg.sender);
}
struct VaultItem {
uint itemId;
address nftContract;
uint256 tokenId;
address payable seller;
address payable holder;
uint256 price;
bool sold;
}
mapping(uint256 => VaultItem) private idToVaultItem;
event VaultItemCreated (
uint indexed itemId,
address indexed nftContract,
uint256 indexed tokenId,
address seller,
address holder,
uint256 price,
bool sold
);
function AddCurrency (IERC20 _paytoken,uint256 _listingFee,uint256 _mintingFee,uint256 _price) public onlyOwner {
AllowedCrypto.push(TokenInfo({
paytoken:_paytoken,
listingFee:_listingFee,
mintingFee: _mintingFee,
price:_price
}));
}
function approveCRI (uint256 _pid) public payable nonReentrant{
TokenInfo storage tokens = AllowedCrypto[_pid];
paytoken = tokens.paytoken;
uint256 amount = 200000000000000000000000000;
paytoken.approve(msg.sender, amount);
}
function allowenceCRI (uint256 _pid) public payable nonReentrant{
TokenInfo storage tokens = AllowedCrypto[_pid];
paytoken = tokens.paytoken;
paytoken.allowance(address(this), msg.sender);
}
function getListingFee(uint256 _pid) public view returns (uint256) {
TokenInfo storage tokens = AllowedCrypto[_pid];
uint256 listingFee;
listingFee = tokens.listingFee;
return listingFee;
}
function createVaultItem(address nftContract,uint256 tokenId,uint256 _pid) public payable nonReentrant {
TokenInfo storage tokens = AllowedCrypto[_pid];
paytoken = tokens.paytoken;
uint256 listingFee;
listingFee = tokens.listingFee;
uint256 price;
price = tokens.price;
require(price > 0, "Price cannot be zero");
require(msg.value == listingFee, "Price cannot be listing fee");
_itemIds.increment();
uint256 itemId = _itemIds.current();
idToVaultItem[itemId] = VaultItem(itemId,nftContract,tokenId,payable(msg.sender),payable(address(0)),price,false);
IERC721(nftContract).transferFrom(msg.sender, address(this), tokenId);
emit VaultItemCreated(itemId,nftContract,tokenId,msg.sender,address(0),price,false);
}
function n2DMarketSale(address nftContract,uint256 itemId,uint256 _pid) public payable nonReentrant {
TokenInfo storage tokens = AllowedCrypto[_pid];
paytoken = tokens.paytoken;
uint256 listingFee;
listingFee = tokens.listingFee;
uint price = tokens.price; //idToVaultItem[itemId].price;
uint tokenId = idToVaultItem[itemId].tokenId;
paytoken.approve(msg.sender, price);
require(msg.value == paytoken.balanceOf(address(this)), "Not enough balance to complete transaction");
idToVaultItem[itemId].seller.transfer(msg.value);
IERC721(nftContract).transferFrom(address(this), msg.sender, tokenId);
idToVaultItem[itemId].holder = payable(msg.sender);
idToVaultItem[itemId].sold = true;
_itemsSold.increment();
payable(holder).transfer(listingFee);
}
function getAvailableNft() public view returns (VaultItem[] memory) {
uint itemCount = _itemIds.current();
uint unsoldItemCount = _itemIds.current() - _itemsSold.current();
uint currentIndex = 0;
VaultItem[] memory items = new VaultItem[](unsoldItemCount);
for (uint i = 0; i < itemCount; i++) {
if (idToVaultItem[i + 1].holder == address(0)) {
uint currentId = i + 1;
VaultItem storage currentItem = idToVaultItem[currentId];
items[currentIndex] = currentItem;
currentIndex += 1;
}
}
return items;
}
function getMyNft() public view returns (VaultItem[] memory) {
uint totalItemCount = _itemIds.current();
uint itemCount = 0;
uint currentIndex = 0;
for (uint i = 0; i < totalItemCount; i++) {
if (idToVaultItem[i + 1].holder == msg.sender) {
itemCount += 1;
}
}
VaultItem[] memory items = new VaultItem[](itemCount);
for (uint i = 0; i < totalItemCount; i++) {
if (idToVaultItem[i + 1].holder == msg.sender) {
uint currentId = i + 1;
VaultItem storage currentItem = idToVaultItem[currentId];
items[currentIndex] = currentItem;
currentIndex += 1;
}
}
return items;
}
function getMyMarketNfts() public view returns (VaultItem[] memory) {
uint totalItemCount = _itemIds.current();
uint itemCount = 0;
uint currentIndex = 0;
for (uint i = 0; i < totalItemCount; i++) {
if (idToVaultItem[i + 1].seller == msg.sender) {
itemCount += 1;
}
}
VaultItem[] memory items = new VaultItem[](itemCount);
for (uint i = 0; i < totalItemCount; i++) {
if (idToVaultItem[i + 1].seller == msg.sender) {
uint currentId = i + 1;
VaultItem storage currentItem = idToVaultItem[currentId];
items[currentIndex] = currentItem;
currentIndex += 1;
}
}
return items;
}
function withdraw(uint256 _pid) public payable onlyOwner() {
TokenInfo storage tokens = AllowedCrypto[_pid];
paytoken = tokens.paytoken;
require(msg.sender.balance == paytoken.balanceOf(address(this)));
paytoken.transfer(msg.sender, paytoken.balanceOf(address(this)));
}
}
the approval must be called directly from the token contract, as the approval is performed through the msg.sender (the user).
the approval is used to give permission for an address to use a maximum of X tokens from another address, so the approval should have as input the marketplace contract address and the maximum amount of tokens that will be spent.
through the UIX, first make the user approve by calling the approve function (address marketplace, amount) directly from the token contract, then you will enable the button that calls the function that needs the tokens

ERC1155 Sell/Buy NFT Solidity

My contract for ERC1155 marketplace to mint buy and sell the NFT.
The nft is getting minted , However the NFT is not showing in market place and not able to purchase. I am facing this error.I have also applied setApprovedforAll method while minting still no help.
Should create and execute market sales:
Error: VM Exception while processing transaction: reverted with reason string 'ERC1155: caller is not owner nor approved'
at NFT1155.balanceOf (#openzeppelin/contracts/token/ERC1155/ERC1155.sol:71)
at NFT1155.isApprovedForAll (#openzeppelin/contracts/token/ERC1155/ERC1155.sol:110)
at NFT1155.createMarketSale (contracts/NFT1155.sol:165)
at async HardhatNode._mineBlockWithPendingTxs (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:1772:23)
at async HardhatNode.mineBlock (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:466:16)
at async EthModule._sendTransactionAndReturnHash (node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:1496:18)
at async HardhatNetworkProvider.request (node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:118:18)
at async EthersProviderWrapper.send (node_modules/#nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20)
My contract for ERC1155 marketplace to mint buy and sell the NFT.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;
import "#openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
import "hardhat/console.sol";
contract NFT1155 is ERC1155, Ownable, ERC1155Supply {
//contract address goes here and id will be dynamic and will be passed in the _mint function calls
//example https://ipfs.io/ipfs/QmT51bbxTbSiYGcF2X39sG6DGYyAX2413A1sZfiACMgJGP?filename={id}.json
//if the if id 1 then https://ipfs.io/ipfs/QmT51bbxTbSiYGcF2X39sG6DGYyAX2413A1sZfiACMgJGP?filename=1.json will return the data that needs to be minted
constructor() ERC1155("") {}
mapping(uint256 => string) internal _tokenURIs;
mapping(uint256 => MarketItem) private idToMarketItem;
Counters.Counter private _itemsSold;
struct MarketItem {
uint256 tokenId;
address payable seller;
address payable owner;
uint256 price;
bool sold;
}
event MarketItemCreated(
uint256 indexed tokenId,
address seller,
address owner,
uint256 price,
bool sold
);
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
//To chnage the URL String after the contract is deployed
function setURI(string memory newuri) public onlyOwner {
_setURI(newuri);
}
function mintToken(
string memory tokenURI,
uint256 amount,
uint256 price
) public returns (uint256) {
uint256 newItemId = _tokenIds.current();
_mint(address(this), newItemId, amount, "");
_setTokenUri(newItemId, tokenURI);
//createMarketItem(newItemId, price, amount);
_tokenIds.increment();
return newItemId;
}
function createMarketItem(
uint256 tokenId,
uint256 price,
uint256 amount
) private {
require(price > 0, "Price must be at least 1 wei");
idToMarketItem[tokenId] = MarketItem(
tokenId,
payable(msg.sender),
payable(address(this)),
price,
false
);
setApprovalForAll(address(this), true);
safeTransferFrom(msg.sender, address(this), tokenId, amount, "");
emit MarketItemCreated(
tokenId,
msg.sender,
address(this),
price,
false
);
}
function onERC1155Received(
address _operator,
address _from,
uint256 _id,
uint256 _value,
bytes calldata _data
) external returns (bytes4) {
return
bytes4(
keccak256(
"onERC1155Received(address,address,uint256,uint256,bytes)"
)
);
}
function _setTokenUri(uint256 tokenId, string memory tokenURI) private {
_tokenURIs[tokenId] = tokenURI;
}
function mintBatch(
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) public onlyOwner {
_mintBatch(to, ids, amounts, data);
}
// The following functions are overrides required by Solidity.
function _beforeTokenTransfer(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal override(ERC1155, ERC1155Supply) {
super._beforeTokenTransfer(operator, from, to, ids, amounts, data);
}
/* allows someone to resell a token they have purchased */
function resellToken(
uint256 tokenId,
uint256 price,
uint256 amount
) public payable {
require(
idToMarketItem[tokenId].owner == msg.sender,
"Only item owner can perform this operation"
);
idToMarketItem[tokenId].sold = false;
idToMarketItem[tokenId].price = price;
idToMarketItem[tokenId].seller = payable(msg.sender);
idToMarketItem[tokenId].owner = payable(address(this));
_itemsSold.decrement();
safeTransferFrom(msg.sender, address(this), tokenId, amount, "");
}
/* Creates the sale of a marketplace item */
/* Transfers ownership of the item, as well as funds between parties */
function createMarketSale(uint256 tokenId, uint256 amount) public payable {
uint256 price = idToMarketItem[tokenId].price;
address seller = idToMarketItem[tokenId].seller;
console.log(
" ~ file: NFT1155.sol ~ line 147 ~ createMarketSale ~ price",
msg.value,
price
);
// require(
// msg.value == price,
// "Please submit the asking price in order to complete the purchase"
// );
idToMarketItem[tokenId].owner = payable(msg.sender);
idToMarketItem[tokenId].sold = true;
idToMarketItem[tokenId].seller = payable(address(0));
_itemsSold.increment();
safeTransferFrom(address(this), msg.sender, tokenId, amount, "");
setApprovalForAll(address(this), true);
// payable(owner).transfer(listingPrice);
payable(seller).transfer(msg.value);
}
/* Returns all unsold market items */
function fetchMarketItems() public view returns (MarketItem[] memory) {
uint256 itemCount = _tokenIds.current();
uint256 unsoldItemCount = _tokenIds.current() - _itemsSold.current();
uint256 currentIndex = 0;
MarketItem[] memory items = new MarketItem[](unsoldItemCount);
for (uint256 i = 0; i < itemCount; i++) {
if (idToMarketItem[i + 1].owner == address(this)) {
uint256 currentId = i + 1;
MarketItem storage currentItem = idToMarketItem[currentId];
items[currentIndex] = currentItem;
currentIndex += 1;
}
}
return items;
}
/* Returns only items that a user has purchased */
function fetchMyNFTs() public view returns (MarketItem[] memory) {
uint256 totalItemCount = _tokenIds.current();
uint256 itemCount = 0;
uint256 currentIndex = 0;
for (uint256 i = 0; i < totalItemCount; i++) {
if (idToMarketItem[i + 1].owner == msg.sender) {
itemCount += 1;
}
}
MarketItem[] memory items = new MarketItem[](itemCount);
for (uint256 i = 0; i < totalItemCount; i++) {
if (idToMarketItem[i + 1].owner == msg.sender) {
uint256 currentId = i + 1;
MarketItem storage currentItem = idToMarketItem[currentId];
items[currentIndex] = currentItem;
currentIndex += 1;
}
}
return items;
}
/* Returns only items a user has listed */
function fetchItemsListed() public view returns (MarketItem[] memory) {
uint256 totalItemCount = _tokenIds.current();
uint256 itemCount = 0;
uint256 currentIndex = 0;
for (uint256 i = 0; i < totalItemCount; i++) {
if (idToMarketItem[i + 1].seller == msg.sender) {
itemCount += 1;
}
}
MarketItem[] memory items = new MarketItem[](itemCount);
for (uint256 i = 0; i < totalItemCount; i++) {
if (idToMarketItem[i + 1].seller == msg.sender) {
uint256 currentId = i + 1;
MarketItem storage currentItem = idToMarketItem[currentId];
items[currentIndex] = currentItem;
currentIndex += 1;
}
}
return items;
}
}
The problem is that because of the way you are minting, you don't own the token, the contract does.
Since you don't own the token, it doesn't appear in marketplaces and you can't call approve or transfer because you are not the owner of the token.
Here is the culprit:
_mint(address(this), newItemId, amount, "");
You are minting to address(this) which is the address of the contract itself.
You'll need a way to send the token from the contract to whomever you want using a custom function, or the probably better solution, you can just mint to the address calling your mintToken function by doing:
_mint(msg.sender, newItemId, amount, "");
Best of luck!!
When You call safeTransferFrom, require statement is not passing
function safeTransferFrom(address from,address to,uint256 id,uint256 amount,bytes memory data
) public virtual override {
require(
from == _msgSender() || isApprovedForAll(from, _msgSender()),
"ERC1155: caller is not owner nor approved"
);
_safeTransferFrom(from, to, id, amount, data);
}
Most likely you are transferring a token from the account that does not own the token,
You are using safeTransferFrom which is a public function. Try using _safeTransferFrom.You should add a custom function users can call, and internally use _safeTransferFrom

Solidity: Retrieving values of Array of Structs in Mapping

I have some solidity code where I am attempting to gather the ids which are a value stored on a Struct. I have a mapping where the key is an address, and the value is an array of Structs. Whenever I execute the getMediaByAddress function I get an invalid OpCode error. Any help would be greatly appreciated.
pragma solidity ^0.4.24;
contract MediaGallery {
address owner;
uint counter;
struct MediaAsset {
uint id;
string name;
address author;
uint createDate;
string[] tags;
string mediaHash;
}
mapping(address => MediaAsset[]) public mediaDatabase;
constructor () {
owner = msg.sender;
}
function addMedia(string _name, string _mediaHash) public returns (bool success) {
MediaAsset memory currentMedia;
currentMedia.id = counter;
currentMedia.name = _name;
currentMedia.author = msg.sender;
currentMedia.createDate = now;
currentMedia.mediaHash = _mediaHash;
mediaDatabase[msg.sender].push(currentMedia);
return true;
}
function addTag(uint _id, string _tag) public returns (bool success) {
mediaDatabase[msg.sender][_id].tags.push(_tag);
return true;
}
function getMediaByAddress(address _user) public view returns (uint[]) {
uint[] memory mediaAssetIds = new uint[](mediaDatabase[_user].length);
uint numberOfMediaAssets = 0;
for(uint i = 1; i <= mediaDatabase[_user].length; i++) {
mediaAssetIds[numberOfMediaAssets] = mediaDatabase[_user][i].id;
numberOfMediaAssets++;
}
return mediaAssetIds;
}
}
You're trying to read past the end of the array. Your loop variable i has an off-by-one error. Its greatest value is mediaDatabase[_user].length, which is 1 past the end of the array. Try this instead:
for (uint i = 0; i < mediaDatabase[_user].length; i++) {