Mint an NFT
About NFTs
The Stardust update allows you to create your own NFTs. You can also use IRC27 for NFTs. This guide will show you how to create an IRC27 L1 NFT using a L2 smart contract.
Example Code
You might want to look into making the function ownable with, for example, OpenZeppelin so only owners of the contract can call certain functionalities of your contract.
1. Check the Storage Deposit
Check if the amount paid to the contract is the same as the required storage deposit and set the allowance.
require(msg.value == _storageDeposit*(10**12), "Please send exact funds to pay for storage deposit");
ISCAssets memory allowance;
allowance.baseTokens = _storageDeposit;
Instead of making the function payable, you could let the contract pay for the storage deposit.
If so, you will need to change the require
statement to check if the contract's balance has enough funds:
require(address(this).balance > _storageDeposit);
- Get the senders AgentID:
ISCAgentID memory agentID = ISC.sandbox.getSenderAccount();
- Create an
IRC27Metadata
struct with all the needed data:
IRC27NFTMetadata memory metadata = IRC27NFTMetadata({
standard: "IRC27",
version: "v1.0",
mimeType: _mimeType,
uri: _uri,
name: _name
});
- Create all the data for the core contract call. To do so, you should create a new
ISCDict
with 2 parameters like specified in the reference docs formintNFT
I
is the immutable metadata we fill with the IRC27 metadata anda
is the AgendID of the owner of the NFT
ISCDict memory params = ISCDict(new ISCDictItem[](2));
params.items[0] = ISCDictItem("I", bytes(IRC27NFTMetadataToString(metadata)));
params.items[1] = ISCDictItem("a", agentID.data);
The full example below calls the IRC27NFTMetadataToString
function, which simply converts the IRC27Metadata struct into a string.
- Call the magic contract
call
function with all the parameters. You should specify the core contract you want to call, which in this case is theaccount
contract, and the function for minting an NFT
ISCDict memory ret = ISC.sandbox.call(
ISC.util.hn("accounts"),
ISC.util.hn("mintNFT"),
params,
allowance
);
- The call return value will contain a
mintID
which we can use in, for example, another contract function to get the actual L1 NFT ID once it is created using theaccounts.NFTIDbyMintID
function
function getNFTIDFromMintID(bytes memory mintID) public view returns (bytes memory) {
ISCDict memory params = ISCDict(new ISCDictItem[](1));
params.items[0] = ISCDictItem("D", mintID);
ISCDict memory ret = ISC.sandbox.callView(
ISC.util.hn("accounts"),
ISC.util.hn("NFTIDbyMintID"),
params
);
return ret.items[0].value;
}
Full Example Code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@iota/iscmagic/ISC.sol";
contract NFTContract {
event MintedNFT(bytes mintID);
function mintNFT(string memory _name, string memory _mimeType, string memory _uri, uint64 _storageDeposit) public payable {
require(msg.value == _storageDeposit*(10**12), "Please send exact funds to pay for storage deposit");
ISCAssets memory allowance;
allowance.baseTokens = _storageDeposit;
ISCAgentID memory agentID = ISC.sandbox.getSenderAccount();
IRC27NFTMetadata memory metadata = IRC27NFTMetadata({
standard: "IRC27",
version: "v1.0",
mimeType: _mimeType,
uri: _uri,
name: _name
});
ISCDict memory params = ISCDict(new ISCDictItem[](2));
params.items[0] = ISCDictItem("I", bytes(IRC27NFTMetadataToString(metadata)));
params.items[1] = ISCDictItem("a", agentID.data);
ISCDict memory ret = ISC.sandbox.call(
ISC.util.hn("accounts"),
ISC.util.hn("mintNFT"),
params,
allowance
);
emit MintedNFT(ret.items[0].value);
}
function getNFTIDFromMintID(bytes memory mintID) public view returns (bytes memory) {
ISCDict memory params = ISCDict(new ISCDictItem[](1));
params.items[0] = ISCDictItem("D", mintID);
ISCDict memory ret = ISC.sandbox.callView(
ISC.util.hn("accounts"),
ISC.util.hn("NFTIDbyMintID"),
params
);
return ret.items[0].value;
}
function IRC27NFTMetadataToString(IRC27NFTMetadata memory metadata)
public
pure
returns (string memory)
{
return string.concat(
'{"standard": "',
metadata.standard,
'", "version": "',
metadata.version,
'", "type": "',
metadata.mimeType,
'", "uri": "',
metadata.uri,
'", "name": "',
metadata.name,
'"}');
}
}