How to Write a Basic NFT Contract from Scratch | Solidity, Remix

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys this is ed rowe today we're going to be writing a simple nft mint contract which is sometimes called an erc721 token all that means is that we're going to use a standard called erc721 to help create and write a simple mint contract for an nft before we start writing our contract i want to mention something very important while writing a simple solidity contract it's simpler than writing regular code because of how it usually doesn't require that much logic it is deceiving because it catches so many amateur developers because one messed up line of code can make your entire contract completely exploitable and waste thousands of dollars unlike regular apps you cannot do quick bug patch fixes on your contract once it has been deployed you'll have to redeploy the entire nft contract which can cost up to thousands of dollars nowadays recently there's been entire nft collections completely fail on launch because some developers have not tested enough they go in they're probably one of the first it's probably one of the first codes that they've written and they go and think this is super easy to program in the right and what they realize is that they have not tested the code and it completely fails you have to absolutely make sure your contract is correctly handled and you make sure that you cannot exploit that contract i cannot stress this enough after having said that we are going to go to remix which is an ide that's on the browser for smart contracts the link is in the description below if you want to get there now the first thing we're going to do we're going to go to contracts we're going to create a new file and we're going to call this simple mint contract dot sol and over here i'm going to increase the font size and the first few things i'm going to do i'm going to add the license [Music] now this license is just an identifier that you want to license your contract and the next thing we're going to add is a pragma solidity and we are going to give it a version of 0.8.4 so this determines the version of solidity that you want to use and this is very highly dependent because every version can make breaking changes so you got to make sure you know which one you want to use all right and the next thing we're going to do we're going to import a few things we're going to import erc 721 contract and we're going to import the ownable contract so these are standards that open zeppelin has set which are very useful in inheriting from for your contract so you can use the standards that are established and these are very safe and well tested community driven contracts that you can use in your writing to make it to make your code writing a lot easier so after we import that we're going to write our contract simple mint contract and we're going to inherit erc 721 and ownable and we inherit using the is keyword and you can chain multiple imports and inherit from multiple contracts now if you're new to solidity these contracts are essential like classes you can think of them as classes in other programming languages where essentially these are just contracts where you would write code in that would run multiple functions or do the things that you want it to do and it can inherit from multiple other contracts as well and so the first thing we're going to do we're going to add some variables in here and we're going to first create a uint 256 variable and we are going to call this mint price and this is is the price that the mint will be costing the consumers and this is a un-256 so this is basically an integer and this is an integer of like the maximum size that you can use and generally this is a big enough number for most integer usage the next variable we're going to create unit 256 public total supply so this will determine right here this will determine the number of maximum tokens that we will have usually mint for nfts they usually have a maximum amount that you want to use but this will keep track of the current number of supplies so as you emit more and more nfts this will keep track of how many there are currently in the total space and then in contrast we have un-256 public max supply so this determines actually the maximum amount that we want so once the total supply reaches the max supply then we want people to not be able to mint any more tokens because it's always a limited number of supply for these nfts and then we have a boolean and we'll put google to determine that it's a boolean and we're going to call this is mint enabled so basically in any kind of nft mint launch you need a variable to determine when people can mint the nfc token you don't want people to mint right away maybe you do once you deploy it but generally you want it not enabled and at the specific set time when you want to launch the mint you want to flip this to be true and then we're going to add something called a mapping so address uint 256. so what this actually does is if you come from javascript this is similar to an object or python this is similar to a dictionary essentially what this will do is we're going to keep track of the number of mints that each wallet has done so we're going to write public minted wallets like so so for every address we want to keep track of how many nft tokens they have minted because we don't not want one wallet to be able to mint all the nfts so generally you want to keep track of it so you have a maximum of one two three or four maybe depending on what you want in this case we're gonna have it set to one but we don't need to write anything for that and then the next step is we're going to write a constructor for every class you have a constructor and this constructor is going to be the function that will be run right when it gets created when this contract gets created so in this case the contract gets created when it gets deployed to the blockchain so this function will basically be run when we deploy it to the blockchain and so we are going to add a constructor for the erc721 because we are inheriting and we want to pass a few things and we're going to call this simple mint so this is just going to be the name erc721 will want the name of the contract that you would want to put and also the symbol and in this case we're going to call it simplemint like that so you can put the address in the name as whatever you want but in this case we're going to have these settings and we're also going to set it payable and finally what we're the one thing we're going to do is we're going to set the max supply and in this case we're just going to have two we're going to keep the maximum amount of nft tokens for this collection just to be two just so we can test out a few things so there's something important to note for solidity if you come from a different programming language a lot of this will be a little bit foreign because you're when you come from other programming languages you worry about performance and the speed of how all your functions interact so you have to be careful of how many loops you do in solidity a lot of that doesn't actually matter what matters is how many variables you are setting and saving into the blockchain so anytime you set and change something like this max supply equals two this is a pretty costly procedure like i mean a lot of this isn't unavoidable at times but you always want to think how i can reduce the amount of variables you want to use in your contract or a smart contract and it's very important so that if i keep changing max supply like this you are wasting a lot of gas a lot of money essentially when you keep doing this this is very very bad because you are pointlessly changing one of these storage variables that exist over here now we'll go over to local variables which are much cheaper and generally preferred over changing any one of these but these are important still because you have to keep track of something that persists whereas local variables do not persist over a long period of time so let's continue on in the first function we're going to create is going to be toggle is mint enabled and we're going to give it let me make sure that's capitalized and we're going to give it an external modifier and are going to give it the only other owner modifier so this function is going to be only accessible by the owner so whoever deploys the contract is going to be the only one who can run this function and that comes from the ownable contract so if you actually look at their contract this is essentially specifying that the person who deploys is the only one who can run this function and the external means that you cannot call this function from other functions inside as well so here we're going to write is mint enabled and we are going to toggle it to the opposite version so just a thing to note we never initialized is mint enabled in solidity when it's undefined that's essentially defaults to false so this is false so anytime you toggle this this is going to set that to true and that's the only purpose of this function you always want to keep your functions very simple in solidity and this is essentially one of those situations and then we're also going to create another function and we're going to create set max supply and we are going to pass in the argument this time and this is going to be a unit 256 and we're going to give it a max supply as the name and we're going to give this underscore as a suffix so good since we have a name called max supply it's a good convention probably to put the underscore after this variable name but there is no real standard like that but i prefer it that way so you can identify which one's your argument and then we're also going to give this an external and an only owner modifier so that owners are the only ones who can modify this and we're going to set max supply equal to the max apply in the argument so what this is essentially going to do is that the owner and not anyone else can modify this max supply so if we ever want to change the number of tokens that this contract can run we can set this max apply manually as a just in case as a fallback finally let's tackle the mint function so we're going to write function mint external payable and the reason why we have this payable is because this is a function that deals with actual money and you're going to be able to make transactions with it we're going to use something called require which is just like an if statement but it's shortened so in this case we're going to say is mint enabled and we're going to write that text minting not enabled so what this is saying is that if mint is not enabled we're going to give an error of minting not enabled and we're going to stop running this function it's going to stop here so these are very convenient ways to make checks and these are very critical very critical for your mint function you need to make sure you have all the correct check statements to make sure your contract is not exploitable so the next require we're going to add is minted wallets message.sender and that has to be less than one and if it's not less than one we're going to say we're going to return an error exceeds max per wallet like so so this one minted wallets so we're tracking the number of wallets we have by making sure that it's less than one so this means that only each wallet can only mint one and this is very important there has been many people who have messed up and they keep track of the balances the user requires statement that checks the number of balances of token in a wallet instead of tracking the number of mints per nft and this is this is a very amateur mistake because what they can do is they can mint the nfts they can either sell those nfts or send those nfts to another wallet and they can mint more and that is exploitable you want to limit the number of mints per wallet and this is important if you have a whitelist function and this is i've seen this happen in many many nfts and it's all of those have failed because of this one line of code that they messed up they did not put this and they could just watch other nft mints but they seem to have just written their own code anyways the next thing we want to do is we're going to require message.value equals mint price and if that doesn't happen you're going to get a wrong value so message.value oh i've not mentioned message.sender or message.value message is a global variable that you can use that gives you good information so message.sender is going to give you the address of the person running this function and the message.value is the value that the user puts or the the user has for the transaction value so like the amount of ether they want to put and if they don't put the correct price compared to the mint price so if they don't put .05 ether then you're gonna get the wrong value so this essentially checks that you they are putting the correct price for the mint and the final check we're going to have is we're going to make sure max supply does not exceed the total supply and if that doesn't happen we're going to have a sold out so essentially if the total supply so this keeps track of how many there are right so if two tokens are currently in supply then we're going to have to give them a sold out if they try to mint the third one so it limits the amount of nfts and finally we're going to get minted wallets and we're going to grab our message.sender and we're going to increase it by 1. the reason why we do this this keeps track of the number of minutes like i mentioned before which is very important and we're also going to increment total supply because we minted a new one and we're also going to pass in the token id equals total supply and if you see this this is actually what i was talking about before this is a local variable you do not want to try and grab this immediately and pass it into um a function or you're going to use that your if you use this directly you're gonna it's gonna cost more gas versus saving it into a temporary local uh variable this is a this makes it so that you can save some gas while you're doing it and finally we're gonna do run a safe mint function and we're going to pass in message.sender with token id so essentially this safement function comes from the erc721 contract so it allows you to mint safely and we're going to pass in the message sender address along with the token id this handles the minting of your nft token and distributes it correctly and it's a very safe thing to use one of their functions because this is a very well tested contract and you want to make sure you always try to use the standards as much as possible now you can go to the erc721 contract to check to check what this does but it's a very simple contract that just mints it mints the nft and gives it to the right person right and that's it that's pretty much a basic mint functionality that we can do for our token and what we're going to do we're going to deploy this and we're going to hit command save or control s depending on your os and when you do that you can go to this second icon right here and you would hit compile but what we're going to do we're going to make sure we're in the right version which is 0.8.4 which is specified over here you can change it to whatever you need and we're going to hit compile once we hit compile we can now go over here to this third one and we can actually deploy our contract now because we imported all of these you're going to see all these different contracts and the one contract that you want to look at is the simple mint contract that you're using so all of these are imported you don't need to worry about that you just have to worry about our contract that we are concerned with and from here we're going to come deploy it and now we can see over here and in here that our contract has been deployed and we have our contract address here now if you look at this this is javascript vm so this is a virtual machine so basically it is an environment running on a local machine and we deploy our contract in here versus a test network which we'll cover a little later because when you run it in a virtual machine it's a lot faster anytime you run these functions it'll run immediately and you can do a lot of performance changes and you can do a lot of things you can configure it manually whereas test networks you can't control as much so there there's some benefits versus using a virtual machine versus a test network and now with this contract what we're going to do is we're going to hit we're going to try to mint right away and once we mint we're going to see minting is not enabled okay and that's because we get this error is mint enabled is not currently enabled which means it's false so if i go down and you can see all these functions all these variables as well which all come from our contract plus these contracts and we want to look at is mint enabled and as you can see it's false so this requires statement is running as expected so the first thing we want to do is we're going to run toggle is mint enabled and now if you click is mint enabled we're going to see that that's true and let's try to mint now if you see here we're going to get a wrong value and that's because we have not specified the value the reason why we got this wrong value is because of this line over here that we had which says message out value equals mint price if you don't get that then it's the wrong value so that means we did not input the correct value because we put value of zero even though we need a 0.05 ether to pass into this particular value so to do that we're going to write we're going to change this to ether and try to write a decimal but because remix does not accept decimals and this is ether we have to convert this into whey so we're going to grab 0.05 and we're going to go to a website called f converter you can find that in the link in the description below and if you pass in 0.05 ether you get this way value and we're going to copy and we're going to paste that and change this back to way now once we try to mint we have now a successful transaction and from there if we try to mint another one because of this line right here we're going to get an error and as you can see if i hit mint exceeds max per wallet so we can omit more than one per wallet so let's go to another wallet so you can choose any one of these these are just random accounts that has been given to you with this vm and we're going to try to mint from this particular wallet and once we hit mint we get a successful transaction let's go to another one though and we're going to put in the same value again we try to mint we're going to get sold out so we're going to reach the maximum supply because our max supply was only two so we already minted one from one account and one from another count and once we hit that no one can mint any more tokens unless we change the max supply so if we go back to the original [Music] address that deployed this contract and we tried to change we're going to use this function set max apply which is over here and we're going to set this to 4 instead and we get a successful transaction now we can go to our fourth wallet and we can mint from here and let's go to another a fifth wallet and we're gonna try to contract and we're gonna mint this should be successful and then if we go to the last account over here and we're gonna go and type in the same value and mint again now we have the sold out so now there's four tokens available and we've all minted so this person wasn't able to mint a token and that's pretty much it we've covered all the require statements so this is a very simplified version of an nft contract and your values and conditions will change depending on the project and what they want sometimes they want a high max supply sometimes they want a higher mint price sometimes they want to set it up so that you can mint more than this amount per wallet or sometimes they want to limit the number of mints per transaction but the max per wallet is a different value so you're going to have to make all those changes dependent on your contract so you want to make sure like i've mentioned before you have to be very careful in writing your mint contract i've seen so many failed launches simply because they don't have the right conditions and one line of code can really mess up and really mess up and like i mentioned a common example was them not having this logic properly set up they tracked it by the number of tokens in their wallet as the limiting factor when it should be the number of of nfts that you've minted per wallet as the main factor and also you always want to keep track of how much you're spending on gas and you can you want to make sure you're not adjusting the gas too much by changing these storage variables too much as minimum as you possibly can so you always want to keep the mint function as simple as possible i've seen a lot of contracts try to do all these fancy things but you want to keep it simple this is one of those things where you want to be making your functions as simple as possible that is the ultimate goal that you want to do as long as you have the main required checks make the other logic as simple as you can anyways if you enjoyed this video please like comment and subscribe and i'll post up more future content let me know what you would like to see
Info
Channel: EdRoh
Views: 50,829
Rating: undefined out of 5
Keywords: EdRoh, nft simple contract, simple contract remix, Solidity contract, nft contract, nft smart application
Id: 8WPzUbJyoNg
Channel Id: undefined
Length: 26min 34sec (1594 seconds)
Published: Wed Jan 05 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.