Solidity NFT metadata loading issue - html

I am creating an NFT collection, and am testing on ropsten. I have my NFT metadata on my website for example boredApes.com/tokens/3.json but the issue is the contract goes to boredApes.com/tokens/3 and not the .json part. How should I change to contract to load this metadata. The current solidity function is
function _baseURI() internal pure override returns (string memory) { return "https://boredApes.com/tokens/"; }

The _baseURI() function sets just the beginning of the URI. You need to override the tokenURI() function as well, appending the .json string at the end of the returned URI.
pragma solidity ^0.8;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol";
contract MyCollection is ERC721 {
constructor() ERC721("MyCollection", "MyC") {
_mint(msg.sender, 1);
}
function _baseURI() internal pure override returns (string memory) {
return "https://boredApes.com/tokens/";
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
// the `super` keyword references the parent function of the same name
string memory uri = super.tokenURI(tokenId);
return string(abi.encodePacked(uri, ".json"));
}
}

Related

How to create many ERC721 tokens sharing the same metadata tokenURI but different TokenId?

I'm actually trying to create an NFT Marketplace, where a user can upload his NFT (create/mint new NFT) and other users can give some Ether and mint the same NFT. Trying to achieve this with the ERC721 standard. Maybe ERC1155 will be a better choice but I have to use ERC721.
So, I think how I can achieve this using ERC721 by minting NFTs with different tokenIDs but with pointing to the same NFT metadata or TokenURI.
I know this is possible as mentioned in this post: https://ethereum.stackexchange.com/questions/59765/two-erc721-tokens-that-refer-to-the-same-metadata
But I can't fo it programatically.
This is how I'm trying: (It's not working, even 1 NFT is not showing on he opensea testnet)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
import "#openzeppelin/contracts/utils/Strings.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
contract navich is ERC721URIStorage, Ownable {
using Strings for uint256;
using Counters for Counters.Counter;
Counters.Counter private _tokenId;
string public baseURI = "ipfs://QmRyezUtChrpvH4i4wKEoPngwTFKHuu4YYjZrSg89wvqVq/";
constructor() ERC721("Wagmi", "Wagmi") {}
function mintNFT() public payable {
uint256 dynamic = 1;
_tokenId.increment();
_mint(msg.sender, _tokenId.current());
_setTokenURI(dynamic, baseURI);
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
return
string(
abi.encodePacked(
baseURI,
tokenId.toString(),
".json"
)
);
}
// function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
// require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
// return "ipfs://QmRyezUtChrpvH4i4wKEoPngwTFKHuu4YYjZrSg89wvqVq";
// }
}
Incidentally, this is not the full Marketplace code.

How to return a struct array in solidity with respect to web3j?

I've a smartcontract in which I've a function getLevels() that returns an array of struct type MLevel, defined at the beginning of smartcontract.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
struct MLevel{
address id;
string levelPrize;
uint levelNo;
uint levelCriteria;
}
contract Test{
MLevel[] public mlevels;
function addLevel(uint _levelCriteria, string memory _levelPrize)public payable{
MLevel memory level;
level.id = msg.sender;
level.levelCriteria = _levelCriteria;
level.levelPrize = _levelPrize;
mlevels.push(level);
}
function getLevels() public view returns(MLevel [] memory){
return mlevels;
}
}
The above smartcontract works absolutely fine in Remix ide. But when I try to create its java wrapper class using web3j, wrapper class does not generate and web3j ends with a weird error part 'struct MLevel' is keyword as shown below in the image

Solidity: calling function from deployed contract reverts

I'm trying to call the getNames() function on the reverse-record ens lookup contract here, but it's reverting. This is my code:
pragma solidity ^0.8.0; pragma experimental ABIEncoderV2;
contract ENStest {
/* ENS Reverse Lookup
Ropsten: 0x72c33B247e62d0f1927E8d325d0358b8f9971C68
Rinkeby: 0x196eC7109e127A353B709a20da25052617295F6f
Goerli: 0x333Fc8f550043f239a2CF79aEd5e9cF4A20Eb41e
Mainnet: 0x3671aE578E63FdF66ad4F3E12CC0c0d71Ac7510C
*/
address public ENSReverseLookupContractAddr = address(0x196eC7109e127A353B709a20da25052617295F6f); // Rinkeby
function addrToENS(address addr) public view returns(string[] memory) {
ReverseRecords ens = ReverseRecords(ENSReverseLookupContractAddr);
return ens.getNames([addr]);
}
}
// ENS Reverse Lookup Remote Contract
abstract contract ReverseRecords {
function getNames(address[] calldata addresses) external view virtual returns (string[] memory r);
}
Anyone know what I'm doing wrong here?
Resolved
I was casting a fixed-length array to a dynamic-sized array.
(h/t https://ethereum.stackexchange.com/a/103894/25695)
Revised code:
function addrToENS(address addr) public view returns(string[] memory) {
ReverseRecords ens = ReverseRecords(ENSReverseLookupContractAddr);
address[] memory t = new address[](1);
t[0] = addr;
return ens.getNames(t);
}

Returning Struct Array in solidity

This is my contract code. Here I'm trying to store the coordinates of a particular trip. While storing the information contract executing fine. But When I retrieve the data, It should give the array of coordinates. But it is throwing an error.
reason: 'insufficient data for uint256 type'
contract TripHistory {
struct Trip {
string lat;
string lon;
}
mapping(string => Trip[]) trips;
function getTrip(string _trip_id) public view returns (Trip[]) {
return trips[_trip_id];
}
function storeTrip(string _trip_id, string _lat, string _lon) public {
trips[_trip_id].push(Trip(_lat, _lon));
}
}
What I'm missing here. Is there any other way to achieve what I'm trying here?
P.S: I'm new to solidity.
First of returning structs is not supported in Solidity directly. Instead you need to return every individual element in the struct as below.
Function xyz(uint256 _value) returns(uint256 User.x, uint256 User.y)
public {}
But then there’s an experimental feature that will help you with returning struct. All that you need to do is add the following after your first pragma line
pragma experimental ABIEncoderV2;
then continue with your code. That should work with no changes to your code.
An example of abiencoderv2 returning struct can be found at this link
It is not possible in solidity to return struct array.
As jlo said in this link, after version 0.8.0, it is possible to return a struct. jlo describes how to set and return an element of array of struct. Here I describe how to set, reset, and return a struct type variable.
I tested it and my test environment is:
private Ethereum network
Geth version 1.10.9-stable (for private network)
Slocjs Compiler version 0.8.7
web3js version 1.5.1
Note, you have to first define the struct type outside of any function inside the contract.
A supper intuitive example code is as follows:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract testContract {
struct funcResultType {
uint[] var1;
string[] var2;
string message;
}
funcResultType private funcResult;
function testSetFunc(string memory inputVar) public payable {
funcResult.var1.push(123);
funcResult.var2.push(inputVar);
funcResult.message = "Done!";
}
function testResetFunc() public payable {
delete funcResult; // reset variales
}
function testGetFunc() public view returns (funcResultType memory){
return funcResult;
}
}
The result of the test with Web3js in the console is as follow:
As you can see the whole variables are accessible. I upload its web3js code in Github in this link.

Is the msg.sender address changed while passing to another contract as a parameter?

I'm here to ask my problem on solidity code.
Here is simple example code. Contract 'Map' has a mapped data. It has each address's T/F values. I created an account X and add it to 'simpleMap'.
Contract 'Ask' lookup mapping data through 'Map' contract. What I expected result when X called askMe() was TRUE but it was always FALSE.
When I called whoIsMsgSender it returns the exact X's account. What's the problem??
pragma solidity ^0.4.24;
contract Map {
mapping (address => bool) simpleMap;
function add(address _address) external {
simpleMap[_address] = true;
}
function isTrue(address _address) external view returns (bool _ret) {
return simpleMap[_address];
}
}
contract Ask {
Map public map = Map(Map's address like 0x~~ just for test);
function askMe() external view returns (bool _ret) {
return map.isTrue(msg.sender);
}
function whoIsMsgSender() external view returns (address _address) {
return msg.sender;
}
}
I tried your contracts in Remix, but askMe() returned true for me. How are you separating the two contracts? Maybe Map is not yet deployed before Ask is trying to call a function on it. I separated the two contracts:
pragma solidity ^0.4.24;
contract Map {
mapping (address => bool) simpleMap;
function add(address _address) external {
simpleMap[_address] = true;
}
function isTrue(address _address) external view returns (bool _ret) {
return simpleMap[_address];
}
}
pragma solidity ^0.4.24;
contract Map { function isTrue(address _address) external view returns (bool _ret); }
contract Ask {
Map public map = Map(MAP_ADDRESS);
function askMe() external view returns (bool _ret) {
return map.isTrue(msg.sender);
}
function whoIsMsgSender() external view returns (address _address) {
return msg.sender;
}
}