Is there a way a smart contract can automatically generate tokenURI using the tokenIDs of erc721 tokens, if we dont want to use other methods. I am a newbie so need some guidance.
1 Answer
Yes, it is possible as you have the functions _mint()
& _setTokenURI()
.
Following is a simple example, which is intended to do the same:
Solidity
// contracts/GameItem.sol
// SPDX-License-Identifier: MIT
pragma solidity <0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract GameItem is ERC721 {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
string private tempURI;
constructor(
string memory name,
string memory symbol,
string memory _tempURI
) ERC721(name, symbol) {
tempURI = _tempURI;
}
function awardItem(address player) public returns (uint256) {
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(player, newItemId);
_setTokenURI(
newItemId,
string(abi.encodePacked(tempURI, uintToString(newItemId)))
);
return newItemId;
}
function uintToString(uint256 v) internal pure returns (string memory str) {
uint256 maxlength = 100;
bytes memory reversed = new bytes(maxlength);
uint256 i = 0;
while (v != 0) {
uint256 remainder = v % 10;
v = v / 10;
reversed[i++] = bytes1(uint8(48 + remainder));
}
bytes memory s = new bytes(i);
for (uint256 j = 0; j < i; j++) {
s[j] = reversed[i - 1 - j];
}
str = string(s);
}
}
Truffle test
const GameItem = artifacts.require("GameItem");
contract("Redroad", async (addresses) => {
const [admin, _] = addresses;
it("works correctly.", async () => {
let id = [];
const gItem = await GameItem.new(
"Invincible Collectible",
"ICB",
"http://www.myserver.com/tokenId="
);
await gItem.awardItem(admin);
await gItem.awardItem(admin);
console.log(await gItem.tokenURI("1"));
console.log(await gItem.tokenURI("2"));
});
});
Following is the output for the truffle test
:
Contract: GameItem
http://www.myserver.com/tokenId=1
http://www.myserver.com/tokenId=2
✓ works correctly. (229ms)
References take from: