Solidity: return array in a public method - solidity

I am trying to create a public funcion that returns an array,
this is the error
Return argument type mapping(uint256 => struct ItemList.Item storage
ref) is not implicitly convertible to expected type (type of first
return variable) uint256[] memory.
pragma solidity ^0.5.0;
contract ItemList {
uint public itemCount = 0;
mapping(uint256 => Item) public items;
event ItemCreated (
uint id,
string proofdocument
);
struct Item {
uint id;
string proofdocument;
}
constructor() public {
}
function createItem(string memory _proofdocument) public {
itemCount++;
items[itemCount] = Item(itemCount, _proofdocument);
emit ItemCreated(itemCount, _proofdocument);
}
function getItems() public pure returns(uint256[] memory ) {
return items; <----------ERROR
}
}
Thanks Andrea

You can get every item in the loop via web3.js library
const array = []
for (let i = 0; i < itemCount; itemCount += 1) {
array.push(contract.getItem(i)) // where getItem do items[I] in solidity
}
Or you can use pragma experimental version:
pragma solidity ^0.5.0;
pragma experimental ABIEncoderV2;
contract ItemList {
uint public itemCount = 0;
struct Item {
uint id;
string proofdocument;
}
Item[] items;
constructor() public {}
function createItem(string memory _proofdocument) public {
itemCount++;
items.push(Item(itemCount, _proofdocument));
}
function getItems() external view returns(Item[] memory) {
return items;
}
}

Related

solidity array mapping with array inside struct

Unable to execture createSchema function. It gives following error
revert
The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the value you send should be less than your current balance.
Debug the transaction to get more information.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Testing {
struct Schema {
mapping(string => string) entity;
}
struct SchemaMapping {
// mapping(string => string) key;
// mapping(string => string) value;
string[] key;
string[] value;
}
mapping(uint256 => Schema) schemas;
mapping(uint256 => SchemaMapping[]) schemaMappings;
function createSchema(uint256 id, string memory key, string memory value) public {
SchemaMapping[] storage schemamapping = schemaMappings[id];
schemamapping[id].key.push(key);
schemamapping[id].value.push(value);
schemas[id].entity[key] = value;
}
function getSchemaElemet(uint256 id) public view returns (SchemaMapping[] memory) {
return schemaMappings[id];
}
}
I adjusted your smart contract. The issue in your original contract is that you were trying to add values into schemaMapping without create SchemaMapping at specific index.
Smart contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
contract Testing {
struct Schema {
mapping(string => string) entity;
}
struct SchemaMapping {
string[] key;
string[] value;
}
mapping(uint256 => Schema) schemas;
mapping(uint256 => SchemaMapping[]) schemaMappings;
function createSchema(uint256 id, string memory key, string memory value) public {
SchemaMapping[] storage schemamapping = schemaMappings[id];
// NOTE: I created an empty space in storage for create object and after bind it with values.
SchemaMapping storage singleSchemaItem = schemamapping.push();
// NOTE: I put values inside keys
singleSchemaItem.key.push(key);
singleSchemaItem.value.push(value);
schemas[id].entity[key] = value;
}
function getSchemaElemet(uint256 id) public view returns (SchemaMapping[] memory) {
return schemaMappings[id];
}
}

Smart Contract NFT how to add price by code to whole items in collection?

Greeting,
Could you tell me how to add price for every item in collection hosted by OpenSea ?
So, I have working code, It created:
1.Collection name (from construct before deploy)
2.NFT symbol (from construct before deploy)
3.URI to ipfs (from construct before deploy ex: ipfs://QmQtP8RNjvcVtKqcPwukgckWF74ojBjzahVzE3qCCnqv4f/
My smart contract example:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/utils/Context.sol";
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/utils/math/SafeMath.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
contract NFT is ERC721Enumerable, Ownable {
using Strings for uint256;
string public baseURI;
string public baseExtension = ".json";
uint256 public cost = 10000000000000000;
uint256 public maxSupply = 10000;
uint256 public maxMintAmount = 100;
bool public paused = false;
mapping(address => bool) public whitelisted;
constructor(
string memory _name,
string memory _symbol,
string memory _initBaseURI
) ERC721(_name, _symbol) {
setBaseURI(_initBaseURI);
mint(msg.sender, 5); // 5- for test
}
// internal
function _baseURI() internal view virtual override returns (string memory) {
return baseURI;
}
// public
function mint(address _to, uint256 _mintAmount) public payable {
uint256 supply = totalSupply();
require(!paused);
require(_mintAmount > 0);
require(_mintAmount <= maxMintAmount);
require(supply + _mintAmount <= maxSupply);
if (msg.sender != owner()) {
if(whitelisted[msg.sender] != true) {
require(msg.value >= cost * _mintAmount);
}
}
for (uint256 i = 1; i <= _mintAmount; i++) {
_safeMint(_to, supply + i);
}
}
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))
: "";
}
//only owner
function setCost(uint256 _newCost) public onlyOwner {
cost = _newCost;
}
function getCost() public view returns (uint256) {
return cost;
}
function setmaxMintAmount(uint256 _newmaxMintAmount) public onlyOwner {
maxMintAmount = _newmaxMintAmount;
}
function setBaseURI(string memory _newBaseURI) public onlyOwner {
baseURI = _newBaseURI;
}
function setBaseExtension(string memory _newBaseExtension) public onlyOwner {
baseExtension = _newBaseExtension;
}
function pause(bool _state) public onlyOwner {
paused = _state;
}
function whitelistUser(address _user) public onlyOwner {
whitelisted[_user] = true;
}
function removeWhitelistUser(address _user) public onlyOwner {
whitelisted[_user] = false;
}
function withdraw() public onlyOwner {
uint256 balance = address(this).balance;
payable(msg.sender).transfer(balance);
}
}
and my item json file example:
{
"description": "Test Description",
"external_url": "http://testurl.com",
"image": "ipfs://QmSrkLg3UR5AUthhCZfrK9nrX3fxJJ4aCJK7B99rUkCa72/4.png",
"name": "Test Name #4",
"symbol": "TNFT",
"collection": {
"name": "TestNFT123_321",
"family": ""
},
"date": 1643919095,
"attributes": {
"Story": "In Caffe",
"Company": "Test Company",
"Some": "thing else"
}
}
On the OpenSea I have created collection name with items, but, with active price button.
What I made wrong?
Thanks for help.
I investigated this issue, so:
Listing items on OpenSea could be with API endpoints (see OpenSea docs, and here).
OpenSea listing could be on mainnet or Rinkeby network only (as of today no Polygon, BSC ...)
There are a lot of clickers, which emulate add item, name, price on Polygon network.
Waiting for API V2 OpenSea =((

Solidity struct arrar

I'm running into a problem with solidity with structures containing arrays, can you help me see what I'm missing?Any help would be greatly appreciated!
struct Info {
uint a;
uint256 b;
uint[] data;
}
mapping(address => Info) infos;
function set() public {
infos[msg.sender].a = 1;
infos[msg.sender].b = 2;
infos[msg.sender].data.push(3);
}
function get() public {
infos[msg.sender].a; //yes It is equal to 1
infos[msg.sender].b; //yes It is equal to 2
infos[msg.sender].data[0]; //The problem here is that anyone calling this function can read data[0]=3
}
I am a little confused as to what you require, but first solution I have provided modifies your Smart Contract such that mapping object infos and the getter function is both private (available only in the Contract defined).
contract test{
struct Info {
uint a;
uint b;
uint[] data;
}
mapping(address => Info) private infos;
function set() public {
infos[msg.sender].a = 1;
infos[msg.sender].b = 2;
infos[msg.sender].data.push(3);
}
function get() private view{
infos[msg.sender].a; //yes It is equal to 1
infos[msg.sender].b; //yes It is equal to 2
infos[msg.sender].data[0]; //The problem here is that anyone calling this function can read data[0]=3
} }
Second solution is to add something called 'require' in the getter function so that only the person who deploys the Smart Contract can view the array index. The constructor function assigns the person who deploys the contract as the 'owner'.
contract test{
struct Info {
uint a;
uint b;
uint[] data;
}
address owner;
constructor() {
owner = msg.sender;
}
mapping(address => Info) infos;
function set() public {
infos[msg.sender].a = 1;
infos[msg.sender].b = 2;
infos[msg.sender].data.push(3);
}
function get() public view{
infos[msg.sender].a; //yes It is equal to 1
infos[msg.sender].b; //yes It is equal to 2
require(owner == msg.sender, 'you cannot read this data, you are not the owner!');
infos[msg.sender].data[0]; //The problem here is that anyone calling this function can read data[0]=3
}
}
Let me know if I have misunderstood your question.

Factory error The called function should be payable

I am using the Opensea Creatures repository (https://github.com/ProjectOpenSea/opensea-creatures.git) to make a Factory and create my ERC721 tokens. I have added the function _setTokenURI (newTokenId, metadataURI); in ERC721Tradable.sol to add the URI when doing mint but it gives me the following error:
The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the value you send should be less than your current balance.
Debug the transaction to get more information.
the files involved are these:
CreatureFactory.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/access/Ownable.sol";
import "openzeppelin-solidity/contracts/utils/Strings.sol";
import "openzeppelin-solidity/contracts/token/ERC721/ERC721.sol";
import "./IFactoryERC721.sol";
import "./Creature.sol";
contract CreatureFactory is FactoryERC721, Ownable {
using Strings for string;
event Transfer(
address indexed from,
address indexed to,
uint256 indexed tokenId
);
address public proxyRegistryAddress;
address public nftAddress;
address public lootBoxNftAddress;
string public baseURI = "https://terrorverso.herokuapp.com/api/token/";
/*
* Enforce the existence of only 100 OpenSea creatures.
*/
uint256 CREATURE_SUPPLY = 100;
/*
* Three different options for minting Creatures (basic, premium, and gold).
*/
uint256 NUM_OPTIONS = 3;
uint256 SINGLE_CREATURE_OPTION = 0;
uint256 MULTIPLE_CREATURE_OPTION = 1;
uint256 LOOTBOX_OPTION = 2;
uint256 NUM_CREATURES_IN_MULTIPLE_CREATURE_OPTION = 4;
constructor(address _proxyRegistryAddress, address _nftAddress) {
proxyRegistryAddress = _proxyRegistryAddress;
nftAddress = _nftAddress;
fireTransferEvents(address(0), owner());
}
function name() override external pure returns (string memory) {
return "Factory";
}
function symbol() override external pure returns (string memory) {
return "FACT";
}
function supportsFactoryInterface() override public pure returns (bool) {
return true;
}
function numOptions() override public view returns (uint256) {
return NUM_OPTIONS;
}
function transferOwnership(address newOwner) override public onlyOwner {
address _prevOwner = owner();
super.transferOwnership(newOwner);
fireTransferEvents(_prevOwner, newOwner);
}
function fireTransferEvents(address _from, address _to) private {
for (uint256 i = 0; i < NUM_OPTIONS; i++) {
emit Transfer(_from, _to, i);
}
}
function mint(uint256 _optionId, address _toAddress, string memory metadataURI) override public {
// Must be sent from the owner proxy or owner.
ProxyRegistry proxyRegistry = ProxyRegistry(proxyRegistryAddress);
assert( address(proxyRegistry.proxies(owner())) == _msgSender() || owner() == _msgSender() || _msgSender() == lootBoxNftAddress );
require(canMint(_optionId));
Creature openSeaCreature = Creature(nftAddress);
if (_optionId == SINGLE_CREATURE_OPTION) {
openSeaCreature.mintTo(_toAddress,metadataURI);
} else if (_optionId == MULTIPLE_CREATURE_OPTION) {
for (
uint256 i = 0;
i < NUM_CREATURES_IN_MULTIPLE_CREATURE_OPTION;
i++
) {
openSeaCreature.mintTo(_toAddress,metadataURI);
}
}
}
function canMint(uint256 _optionId) override public view returns (bool) {
if (_optionId >= NUM_OPTIONS) {
return false;
}
Creature openSeaCreature = Creature(nftAddress);
uint256 creatureSupply = openSeaCreature.totalSupply();
uint256 numItemsAllocated = 0;
if (_optionId == SINGLE_CREATURE_OPTION) {
numItemsAllocated = 1;
} else if (_optionId == MULTIPLE_CREATURE_OPTION) {
numItemsAllocated = NUM_CREATURES_IN_MULTIPLE_CREATURE_OPTION;
}
return creatureSupply < (CREATURE_SUPPLY - numItemsAllocated);
}
function tokenURI(uint256 _optionId) override external view returns (string memory) {
return string(abi.encodePacked(baseURI, Strings.toString(_optionId)));
}
/**
* Hack to get things to work automatically on OpenSea.
* Use transferFrom so the frontend doesn't have to worry about different method names.
*/
function transferFrom(
address _from,
address _to,
uint256 _tokenId,
string memory metadataURI
) public {
mint(_tokenId, _to, metadataURI);
}
/**
* Hack to get things to work automatically on OpenSea.
* Use isApprovedForAll so the frontend doesn't have to worry about different method names.
*/
function isApprovedForAll(address _owner, address _operator)
public
view
returns (bool)
{
if (owner() == _owner && _owner == _operator) {
return true;
}
ProxyRegistry proxyRegistry = ProxyRegistry(proxyRegistryAddress);
if (
owner() == _owner &&
address(proxyRegistry.proxies(_owner)) == _operator
) {
return true;
}
return false;
}
/**
* Hack to get things to work automatically on OpenSea.
* Use isApprovedForAll so the frontend doesn't have to worry about different method names.
*/
function ownerOf(uint256 _tokenId) public view returns (address _owner) {
return owner();
}
}
ERC721Tradable.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/token/ERC721/ERC721.sol";
import "openzeppelin-solidity/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "openzeppelin-solidity/contracts/access/Ownable.sol";
import "openzeppelin-solidity/contracts/utils/math/SafeMath.sol";
import "openzeppelin-solidity/contracts/utils/Strings.sol";
import "openzeppelin-solidity/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "./common/meta-transactions/ContentMixin.sol";
import "./common/meta-transactions/NativeMetaTransaction.sol";
contract OwnableDelegateProxy {}
contract ProxyRegistry {
mapping(address => OwnableDelegateProxy) public proxies;
}
/**
* #title ERC721Tradable
* ERC721Tradable - ERC721 contract that whitelists a trading address, and has minting functionality.
*/
abstract contract ERC721Tradable is ContextMixin, ERC721Enumerable, NativeMetaTransaction, Ownable, ERC721URIStorage {
using SafeMath for uint256;
address proxyRegistryAddress;
uint256 private _currentTokenId = 0;
constructor(
string memory _name,
string memory _symbol,
address _proxyRegistryAddress
) ERC721(_name, _symbol) {
proxyRegistryAddress = _proxyRegistryAddress;
_initializeEIP712(_name);
}
/**
* #dev Mints a token to an address with a tokenURI.
* #param _to address of the future owner of the token
*/
function mintTo(address _to, string memory metadataURI) public onlyOwner {
uint256 newTokenId = _getNextTokenId();
_mint(_to, newTokenId);
_setTokenURI(newTokenId, metadataURI);
_incrementTokenId();
}
/**
* #dev calculates the next token ID based on value of _currentTokenId
* #return uint256 for the next token ID
*/
function _getNextTokenId() private view returns (uint256) {
return _currentTokenId.add(1);
}
/**
* #dev increments the value of _currentTokenId
*/
function _incrementTokenId() private {
_currentTokenId++;
}
function baseTokenURI() virtual public pure returns (string memory);
function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
super._burn(tokenId);
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId)
internal
override(ERC721, ERC721Enumerable)
{
super._beforeTokenTransfer(from, to, tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
/**
* Override isApprovedForAll to whitelist user's OpenSea proxy accounts to enable gas-less listings.
*/
function isApprovedForAll(address owner, address operator)
override
public
view
returns (bool)
{
// Whitelist OpenSea proxy contract for easy trading.
ProxyRegistry proxyRegistry = ProxyRegistry(proxyRegistryAddress);
if (address(proxyRegistry.proxies(owner)) == operator) {
return true;
}
return super.isApprovedForAll(owner, operator);
}
/**
* This is used instead of msg.sender as transactions won't be sent by the original token owner, but by OpenSea.
*/
function _msgSender()
internal
override
view
returns (address sender)
{
return ContextMixin.msgSender();
}
}
and Creature.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./ERC721Tradable.sol";
/**
* #title Creature
* Creature - a contract for my non-fungible creatures.
*/
contract Creature is ERC721Tradable{
constructor(address _proxyRegistryAddress)
ERC721Tradable("ExampleNFT", "EXA", _proxyRegistryAddress)
{}
function baseTokenURI() override public pure returns (string memory) {
return "https://example.com/api/token/";
}
function contractURI() public pure returns (string memory) {
return "https://creatures-api.opensea.io/contract/opensea-creatures";
}
}

How can i push element on array defined on struct in Solidity?

I'm starting to approach with Solidity (current version 0.8.0) smart contracts, but I can't understand why the compiler print me an error during the push.
The problem is the following: I'm trying to push an element on array in struct but compile failed with error: Copying of type struct memory[] memory to storage not yet supported.
Here my example:
contract TestNFT is ERC721, Ownable {
struct Child {
string name;
}
struct Father {
string name;
Child[] childs;
}
mapping(uint256 => Child) private _childs;
uint256 nextChild = 0;
mapping(uint256 => Father) private _fathers;
uint256 nextFather = 0;
constructor(string memory name, string memory symbol)
ERC721(name, symbol)
{}
function mint(
string memory name
) public onlyOwner {
_safeMint(msg.sender, nextCharacter);
_childs[nextChild] = Child(name);
nextChild++;
}
function mintFather(string memory name) public onlyOwner {
_safeMint(msg.sender, nextClan);
_fathers[nextFather] = Father(name, new Child[](0));
nextFather++;
}
function insertChildToFather(uint256 fatherId, uint256 childId)
public
onlyOwner
{
Child memory child = _childs[childId];
_fathers[fatherId].childs.push(child);
}
}
How can I fix the insertChildToFather function?