Faucet Smart Contract Tutorial | Solidity Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys what's going on in this tutorial we'll be writing a faucet smart contract for an erc20 token faucets are programs that give out a specified amount of tokens to anyone who requests them usually rate limited by a certain time interval there are a couple of reasons you might want a faucet contract to distribute your tokens for example as a promotion to increase ownership of your token or simply to provide tokens to developers for testing purposes even if you don't have your own erc20 token or don't think you need a faucet application this is a great contract to practice and study because it contains a lot of elements and patterns that are widely used in many different kinds of smart contracts some of the things this video will cover include interfaces events withdrawals rate limiting or working with time intervals for detecting elapsed time and of course working with sending and receiving tokens so in this video we'll focus on the solidity smart contract for the faucet and then we'll build the faucet ui using web3 in a future video so if that sounds interesting stick around and don't touch that dial [Music] all right guys so let's go ahead and jump into visual studio code or the ide of your choice now this video is sort of an informal continuation of my last video on creating an erc20 token so now we're creating a faucet to distribute those tokens so i'm going to go ahead and continue using that existing project now i'm not going to really go over the entire process of how to set up a project from scratch using hardhat since i covered that in that last video but if you guys want to review that please feel free to check out that video for the step-by-step process link in the video description below so i have made one minor change since the last video and if you recall we were targeting the rinkaby test network for our erc20 token well with this project i'm now targeting gourley and big shout out to channel subscriber stefano for bringing this to my attention that rinkeby and robsten both are going to be retired in the future due to changes relating to the merge which incidentally is taking place today so in order to make that change it's very simple there's just a couple of touch points the first one is that i've created a new environment variable in my.env file and i'm showing you the dot emv.example just so i don't expose my secrets there and then we have to make a reference to that in hardhat config if you remember there was a networks config object and i've just added a new network right here for go early and i'm referencing that new dot env file right here for endpoint so also don't forget to log into infuria and grab your go early endpoint and copy and paste it right into your env file all right so with that out of the way let's get to work on our faucet contract so the first thing i'm going to do is go into my contracts folder and create a new file and i'll call that faucet.sol and let's go ahead and pop open that file and i'm just going to go ahead and paste in my license identifier comment and my pragma solidity statement after that we'll create a contract definition so i'll say contract faucet and give it some curly braces go ahead and save that next let's go ahead and create a state variable for the contract owner so this is going to be a variable of type address we're going to make it payable because we want the owner to be able to withdraw his or her tokens at any time from the contract and we'll call it owner okay so let's take a second to just think through how this contract is actually going to work so we're creating the faucet as a separate contract and we're going to pre-load it with our erc20 token so there'll be a limited amount of token that the faucet has control over that can then distribute to whoever requests tokens i've seen another approach where the faucet code is actually integrated within the erc20 smart contract itself and there's no reason you can't do that however i don't really like the idea i don't recommend it because then you're in essence you're minting new tokens every time someone requests them so you may create your erc20 token you may initially send a certain percentage back to the owner wallet and leave the remaining percentage in the contract to be distributed in various ways with that approach though i think it's too tightly coupled and if there were ever to be a bug or anything wrong with the code somebody could potentially drain all of those funds right so the great thing about having the faucet contract separate is that you can pre-load it with smaller amounts of tokens which i think is an overall safer approach so we're going to be dealing with an erc20 token within our smart contract we're going to have to figure out how to do that because we want to call various methods on our erc20 tokens such as transfer and balance of for example so in order to work with another contract or call methods on another contract from this contract we need to use something called an interface all right so let's look at the syntax of how to declare an interface i'm going to go right above my contract and i'm going to use the interface keyword and then simply give it a name and i'm going to say e i erc 20 for interface of erc20 okay so basically this this interface is like a blueprint sort of mapping out all of the functions and methods that are available on an erc20 contract so that our compiler knows what methods are out there what are available for our code to call okay so interfaces allow one contract to talk to another contract on the blockchain okay there are a couple of things to remember about interfaces so we we only define the functions that we actually need to use so we don't have to cover all of the functions of a erc20 for example in this case an interface cannot have any function implementation only the function signature okay so for example let's define our first function i'm going to say function transfer we'll definitely need that we'll be transferring erc20 tokens around all right and so the transfer function on our erc20 takes two parameters address of type or address 2 and uint 256 amount okay all right now we'll say external so one thing to remember is all function definitions and interface have to be external because they're going to be called from another contract right view and then we'll add the return type returns this returns a boolean value and of course if you can't remember exactly what the function signature looks like you can go out to open zeppelin for example and take a look at the documentation for erc20 and then that's it so you'll notice there's no function body so interfaces they don't have any implementation they don't have any body and so an interface kind of looks like a contract skeleton or blueprint all right let's go ahead and i think we only need one more function so we'll say function balance of we need to be able to check account balances of our erc20 and so this takes one parameter address account external because all interface functions are external view returns also uint 256 or not also but you went 256 all right go ahead and save that let's take a look at how we can use our interface so the basic idea is we're going to call our interface passing in the address of the contract that we want to represent that will in essence create a local instance of that contract which we can then call methods on in our code so the first thing i'm going to do is declare a state variable of type ierc20 and we'll say public token next we'll define our constructor and this is going to take one parameter of type address and we'll call this token just like to be pretty explicit with my variable names and we'll make this a type payable just in case we want to send in any tokens with the contract deployment all right so now we'll we'll create an instance of the erc20 contract using the interface and assign it to token so i'll say i erc 20. we'll pass in the token address so at this point token will essentially contain an instance of our erc20 contract that we can then call methods on throughout the rest of our code now while we're here in the constructor we'll go ahead and set the owner this is the contract owner this is going to be cast to payable and we'll say message dot sender okay and go ahead and save okay so next let's go ahead and write the main function that users will call in order to request tokens so i'm going to say function request tokens this will be a public function and the main functionality is going to be calling a method from our token instance token.transfer and this takes two parameters message.sender the to address and then the withdrawal amount okay so we haven't yet defined this variable we'll do that right now so i'm going to go back up to our state variables and let's create a new variable for our withdrawal amount okay uin256 this can be public and we'll say withdrawal amount let's set the initial value to 50 tokens all right and now we can use since our token has 18 decimal places we're going to say 50 times 10 to the power of 18. all right to represent those 18 decimal places okay great so we're not done yet obviously we're going to want to put a couple of checks in place because we don't want invalid accounts to be able to call this function we don't want someone to be able to repeatedly call this function and essentially drain the faucet account so what we can do is we can leverage a global variable called block.timestamp to give us an approximate value of the current the time of the current block okay and then we can add a certain time interval to that to create a future uh sort of soonest access time that we can then check in this function to see if the user is eligible to withdraw tokens from the contract okay so first i'm going to add a check to make sure that the request is originating from a valid account okay so we check message.sender is not equal to address of zero a zero address basically invalid address okay so we have to pass this this check first the next check is going to ensure that the smart contract has a sufficient balance to handle the request all right so we'll say token.balance of address this now address this again that refers to the balance of this contract this smart contract so we make sure that is greater than or equal to the requested withdrawal amount which is 50 tokens okay and if it's not we say insufficient balance and faucet for withdrawal request and so the final require statement is going to ensure that enough time has elapsed since since the last request in order to request another withdrawal of tokens so we said that we can use block.timestamp to get the current time and then add some sort of time interval to that now we need to record that along with the user's address and so to do that we're going to use a mapping so i'm going to go right above my constructor here and i'm going to say mapping now we've got to enter the types of mappings that we want so i'll say address it's going to be a mapping of address to uint256s okay so we'll have the address of the person calling the contract or the wallet calling the contract and the time interval and we'll call this next access time just like that okay so next we need to actually declare a variable to hold the time interval that we want to set so how long do we want to make our users wait before they can withdraw tokens again or before they can request tokens again i think for the purpose of this tutorial we're going to set it fairly small to one minute just for testing purposes but of course you can use any value you want here so i'm going to create a new uint256 i'm going to call this lock time okay and i'm gonna say one minute so i can take advantage of the minutes global variable here to make this easy to write out one minute yeah they don't change it for singular so one minutes two minutes three minutes so set this to whatever you like i suggest a lower value for testing just until we make sure everything's working correctly so i can come down and compose my require statement now okay so we're gonna say require block dot time stamp must be greater than or equal to next access time of the current address so message.sender okay all right now let's write our error message whoops that jumped down there for some reason okay let's say insufficient time elapsed since last withdrawal try again later so yeah you can make the message be whatever you like of course and i'll just fix the spelling here there we go all right so the final thing we need to do is actually set the new time whenever they request the token so right before the transfer i'm going to space this out just a little bit more and i'll say next access time of message.sender okay will be equal to block dot time stamp plus lock time great okay go ahead and save that okay so the next thing we're going to do is to create a receive function so that we can actually preload our faucet with tokens because remember with this model we're not actually minting directly from the erc20 we're pre-loading the faucet with tokens so that users can then request them so to do that to send funds to any smart contract we need a receive function all right so i'm going to go right down here and say receive should be external and payable in order to receive funds okay now inside this receive function what we can do is we can broadcast an event so if you're familiar with event driven architecture the way it works it's really pretty simple basically part of the code broadcasts an event in response to some action that's taken and it can send a payload of data that describes that action and then other parts of the code can listen to those events and react accordingly whether that be call an event handler or or something else or do some logging so we can broadcast an event when whenever the smart contract receives funds so the way we can do that i'm going to go back up to the top of the code here and let's see i'm going to define an event i'll go underneath the lock time the one that we just set up in the last last section so i'll say event to define a new event i'm going to say deposit name of the event and then the data that we want to be able to send so i'm going to create two parameters here i'm going to say the address of the externally owned account that made the deposit and then the amount so this will be a uint256 and we'll say amount all right so we've defined an event right here with that line and now in order to actually send or broadcast the event we can use the emit keyword right deposit and then we can send in message.sender that that'll give us the address of whoever made the deposit and we'll say message.value all right great all right so what other kind of functions might be useful for our faucet contract i usually like to implement a basic function to just return the balance of the contract mostly for testing just to see how many tokens the contract currently holds all right so i'll say new function function get balance no parameters that's going to be external because we want to be able to call it from you know remix or or another um d app or something like that so this is going to return a uint 256. yeah and we'll call the token instance so we'll say token dot balance of and then we'll say address this to give us the smart contract address all right great that's all we need to do there go ahead and save that now we might want a couple of setters we might want to set some of these parameters that we've sort of hard coded up here like the withdrawal amount and what else the the lock time so let's set up some setter functions for those two just to give us some flexibility if we change our mind later alright so we'll start with withdrawal mount function set withdrawal amount okay so we want it to take in the new amount uint256 amount all right now we we probably want to gate this or limit this to only a lot of these setters so that only the owner of the contract can call them all right so i'm gonna i'm gonna say only owner even though we haven't set up this axis modifier yet we'll do that in just a minute this is a pretty standard pattern only owner all right so we'll set the new withdrawal amount to our variable that we've set up previously so this is going to be the amount and we want to be able to pass in the amount in sort of human readable numbers not worry about the 18 decimal places so what we can do is take care of that here oops so i'm going to use this pattern pattern again where we say times 10 to the 18th all right to give us our 18 decimal places all right great and no need to return it because this is setting a variable so we are good there um let's go ahead and set up that axis modifier before i before i forget so i'll just go down and i like to have this at the bottom usually but it doesn't matter so we'll say modifier only owner and then we'll put our require statement in here and oops all right so message.sender must equal owner or else we display this message only the contract owner can call this function great all right and don't forget this special bit of syntax just to underscore to sort of designate the rest of the the function body that this is being applied to all right so now we're good with our only owner next we'll write our set lock time function okay so that we can modify the lock time as we need to so i'll say set lock time and this will take a uint 256. we'll say amount so we'll we'll send in the amount in minutes and then apply that and again i'll make this a only owner function all right so inside the function body we're going to be setting to the lock time variable right and so we'll say amount times 1 minutes and that'll give us the total amount of minutes for the interval that the user needs to wait before requesting new funds go ahead and save that okay and finally we need to set up a withdrawal function so that the owner of the contract can withdraw all their funds at any time for any reason they want to so i'm going to say function withdrawal external and only owner very important all right so inside this function we'll say token dot transfer message us sender and we'll say the full balance okay so token balance of address of this contract all right all right i think that looks good go ahead and save all right so we have one event that we're using for the deposit but i think there are a couple of more we can actually add and erc20 actually has an event for transferring so we can define that back up here in the interface event transfer and then here's what the signature looks like a couple of parameters here address indexed from oops address indexed 2 and uint256 value now the index keywords that you might see in some events what that means basically is that you can search by these parameter names in event logs after these events are fired so that's just something that helps you basically search the logs by the way i can add that here as well and you can have up to three indexed parameters per event i believe there we go all right and let's create one more event for withdrawal so i'll say with draw and this is going to be address 2 and an amount by the way you don't have to have these events this is just kind of extra here yeah we can also say indexed yeah so totally optional uh if you don't feel like messing with this then uh you can you know this will obviously function just fine without the events okay just sort of the icing on the cake all right so now we can actually go ahead and use that withdrawal event down in the withdrawal function so emit withdrawal and this is going to take a address to an amount right so basically the same as the the signature for the actual transfer so i'll just copy and paste that all right so before we go any further here i've just got to fix one thing real quick we've got some syntax highlighting here alerting me to the fact that we're not returning a uint256 as our function signature says we should be so i'm just going to go ahead and add the return statement here i forgot to add that earlier so just make sure you have that return statement in the get balance function all right so next we're going to take a look at writing a deploy script for our faucet contract oh and by the way one more thing about the interface so we wrote the interface out manually by hand just because i wanted to show you guys the process however there is an interface that we can utilize from open zeppelin since we've already installed the opens up on contracts so we could just where is it go down under opens up on contracts token um where is it common no oh it's under erc20 and then right down here you see there's a ierc20 all right and so this is an interface so you could just import this um it's got every single function so you know we didn't need every single one so maybe we actually did the right thing here by just you know having the minimal amount of code but we could just use an import statement and bring in this interface directly instead of writing it out manually so just want to give you that option just in case you want to do it that way as well all right so let's go ahead and write a deploy script for the faucet contract so i'm going to go under the scripts folder and create a new file and i'm going to say deploy faucet just to differentiate it from our token script dot js okay and what i'm going to do just to save a bit of time i'm going to actually open up our our first deploy script and copy and paste the code and just change what we need because it's pretty much the same all right so we'll just change you know ocean token to faucet and just remember to maintain the capitalization so the first two it's uppercase and then where we're actually referencing the instance it's lowercase okay and a couple more instances right here and right here and i'll change this to say faucet contract deployed faucet address all right so um the one thing that needs to change oh i forgot right here as well it's uppercase faucet so remember our constructor parameter for the faucet is going to be the token address right so what we need to do is first we need to deploy our token our erc20 token right and then we need to record the address and we need to copy and paste it in here and then go ahead and deploy our faucet so that's exactly what we're going to do next all right so first i'm going to open up a terminal window and we're going to go ahead and deploy our token if you guys don't have the token code again that can be downloaded from this the project repository link in the description of this video you guys can download that code and follow along with these deployments right here all right so i'm going to make sure i'm in the top level folder which in this case it's ocean token okay all right now i simply need to issue a hardhat command to go ahead and deploy our token so that's going to be npx hard hat run we'll specify a network with a network flag we're going to say okay and then scripts dash deploy so the deploy.js is for the token deploy faucet obviously for the faucet let's go ahead and run that okay and it looks like our token contract has deployed successfully so what i like to do is just sort of grab this address and save it in a notepad for safe keeping and then we can go back to our faucet deploy script and we'll go ahead and add that address in in between two quotes as a string and now we are ready to go ahead and deploy our faucet contract okay let's deploy the faucet script now so i'll say npx hard hat run dash dash network g-o-e-r-l-i scripts deploy faucet dot js and let's go ahead and run that all right so our faucet contract has successfully deployed and so i'm just going to quickly grab this address and paste it into my notepad for safekeeping and reference all right so what we're going to do next is we're going to use the online remix ide to connect to our contract on the testnet and just do some testing using our metamask wallet all right so one thing we could do before we even do any manual testing is to go out to the gorly block explorer and just make sure that we can find our contract here so this is the address for the faucet contract and let's just see what it comes up with hopefully we'll find something yep that looks about right about nine minutes ago from my wallet address value zero ether small transaction fee so that looks good yeah i don't think we'll be able to see anything here all right great so that's yeah that's good enough that tells me that our contract is in fact deployed to the blockchain so next let's go over to remix.ethereum.org and this is the remix ide which you've seen in many of my videos so i'm not going to go through too much setup here or anything but basically we'll open up the contracts folder and we'll we'll utilize one of these existing contracts here so here's the ocean token one that i used before so i'll take contract number two here and just rename it and we'll just call this faucet okay go ahead and save that and i'm just going to delete everything in this sample contract right here all right so what we need to do in order to connect to a remote contract is we need to first of all just grab all of the contract code and copy it into the file so i'm just gonna control c all of this and where to go back here and go ahead and paste that in all right so this this code basically needs to match what's out there on the blockchain all right and so then we can go over to compile make sure this is compiled make sure your compiler is set to the right version and then once that's complete all right let's switch over to our deploy tab and we want to make sure that we've selected injected provider meta mask so that we can control all the transactions with our metamask wallet so that should open up meta mask and prompt us to go ahead and connect okay so go ahead and accept that and we're connected to remix great all right so the next thing we need to do is just grab the address of our remote contract and go ahead and paste it in the at address field so grab that right there and make sure you and go ahead and click on add address and we should see our deployed account down at the bottom so i'm sorry our deployed contract so go ahead and expand that and we can see all the methods and state variables from our contract so we can start to test some of these utility functions down here to get balance that should have an initial value of zero since we haven't pre-loaded our contract with anything yet perfect and our lock time should be one minute or it might show us 60 seconds so let's check that out perfect our token that should match the token address of our erc20 token that looks good we can go ahead and verify by comparing with what we have in notepad that looks perfect and then the withdrawal amount that's going to be 50 tokens and there we go 50 followed by 18 zeros all right so we can do some further testing here we can test the request tokens function and that should fail off the bat because remember we said that there's got to be tokens in the contract and for anyone to request any tokens so make sure you're connected to the to the right network and yeah there we go so we get a message warning us that the transaction is likely going to fail and we can even see our error message that we coded okay so let's go ahead and grab the faucet address and the next step what we need to do is actually send in some tokens to the contract that we can work with so we'll pop open metamask and let's see i'm going to click on send to make sure you're again make sure you're on the right test network go ahead and paste in the faucet address and let's see i should be able to switch to our erc20 token over here oh you know what what we need to do is actually import the token first because i forgot we'd done a previous deployment but we redeployed today so we need to go ahead and click on import tokens go ahead and grab the address of our erc20 token paste it in there it's recognizing the ticker symbol and the decimal places go ahead and click on import tokens there we can see 70 million oct and that's per the specification in our smart contract so we can try our send one more time let's go back and grab the faucet address uh there's a lot of copying and pasting of addresses in web3 always fun so we can now see our token there in the drop down and select it and let's go ahead and do 200 we'll send in 200 erc20 tokens to give us something to work with all right and that transaction will take a few seconds to settle all right so now we can recheck the token balance on our contract and make sure that we've got 200 now great that's a good sign all right so that's working the next thing we can do is test our request token function all right see if we can drip from the faucet so i'm going to go ahead and switch to account two for this test and uh when you do that just make sure that you've imported the erc20 token so that you can see you know probably a zero starting balance but in any case just to make sure that you can tell that it's been incremented after this after this test so it looks good so let's go ahead and invoke request token oh gas estimation error with the following message see below the transaction execution will likely fail do you want to force sending that's strange because i should have more than enough gas to handle a simple transfer transaction that's weird let's go ahead and send this anyway and see what happens all right i'm going to go ahead and confirm it and let's just monitor the output down here to see what happens all right and it did fail so uh what we can do is pop open the debugger to see if there's anything useful uh so if i do start debugging which it does that um i guess automatically so basically this little toolbar represents all the steps in the operation stepping through the code and i could just use this like any other debugger there are a couple of useful things i can look at here this will give me the solidity state in other words all my state variables so i can inspect them everything looks okay now i mean everything looks correct the step details will kind of tell you what's going on every step of the way and then you can look at the global variables down there and you can see all the items on the stack and all the up codes as well so let's just take a quick look here okay and we can see memory being allocated over there down here in the stack this is just some memory being allocated before a variable is actually assigned now it's populated but i'm not really seeing anything specific that alerts me to what's going on here so yeah i mean i'm not seeing any red flags here everything is looking as i would expect it to yeah it seems to be frozen up at this point and i'm not really getting much useful information out of here so i think what i'm gonna have to do is go back to the code and just sort of look through things manually and see if i can spot any any bugs all right well one thing i noticed is that i spelled withdraw wrong so i'm going to quickly fix that that's not the cause of the error that's because i i misspelled it consistently so but i'll take this opportunity to fix that so i'll do a quick find and replace there just for good measure all right um and so since this is sort of failing i mean when i look at the request token i don't see any problem with the require statement and i don't see any problem with the um sort of the time related variables uh we're doing this token transfer so that's a bit of a black box but we've toasted we've toasted we've tested the token so we know that code is solid so what does that leave basically in the picture the interface and so that's the first thing i'm going to look at and so you know i could import the interface and just automatically um sort of make sure that all this code is is correct or sort of take my um you know human user error out of the picture really easily but i'm just going to take a quick look here let's see token here c20 all right so here's the official interface so since there's just a couple of methods i should be able to like quickly check these let's see transfer that's a transfer event yeah transfer and i saw something change right away that i had a view here this is obviously not a view function because transfer causes a change to occur on the blockchain like we're actually changing the token balances so that's a write operation to the blockchain so that actually could have been the error right there let's check balance of just to make sure i probably should have manually copied these in the first place but here we are so uh yeah that's the same and um event that was at the top all right so with those changes let's go ahead and redeploy our faucet contract so i'm going to go back up press the up key to get back to this command and go ahead and run that alright our contract finished deploying so again i'm just going to grab the address and save it in my notepad replacing the old one okay and let's go back out to remix and so make some more space here and basically we've gotta just uh delete all that code and copy and paste everything in again okay good and i'm going to clear this logging out all right let's go back and make sure that well let's delete this old contract we'll make sure it's compiled and everything is good in the meantime i'm going to grab the address okay copy that and let's go down to our deployment tab and i'll just replace the old address with a new one and we'll go ahead and redeploy all right so there's our new contract uh since we've already tested this we'll just do a very quick run through make sure things look okay lock time yep token okay good so far so good so we'll just go ahead and send it some tokens right away come on metamask all right and i'm just gonna do another send let's do the same thing we'll stick with 200 go ahead and sign that transaction and send it on over all right that's complete so let's recheck the balance there we go there's our 200 coins and let's go and switch back to account number two all right i'm gonna do request all right this time it's opening up that's a very good sign i can't believe it see the interface was the problem so it's so important to make sure that all of the interface function signatures match what you're actually trying to interface with all right let's check our balance of account two and there's our 50 oct excellent so that worked right now i'm going to quickly try another test within a minute here and that should not be allowed to happen right because of our time lock so let's try again great so we get an error insufficient time elapsed since since last withdrawal which is exactly what we want to see great all right so we just really have to wait like 30 more seconds and try it again and we should be allowed to do it after one minute all right so let's just pause for about a minute and we'll retry that all right let's try another token request this time it's opening up again to ask me to sign the transaction so it's going to allow us to go ahead and make that request so it looks like our time lock is working great and i can go ahead and request new tokens i'll immediately try another one let's just test this again the only reason that allowed it to happen that time is because the time lock had not actually been saved to the blockchain so if i do it again it won't work and let's just see if we have 100 oct now perfect okay so that part seems to be working great that's our main functionality so that's important let's try to withdraw the funds let's try to withdraw all the funds with account two we should not be able to do this execution reverted the only only the contract owner can call this function perfect great all right so um let's check a few things with the owner account just to make sure that we can use the setters and withdraw the funds all right so i'm going to switch back to account number one and let's go ahead and withdraw all the funds this time it allows me to do that so i'll go ahead and sign this transaction confirm now we can check the contract balance once this settles and it should be back down to zero it'll take a minute for that to be reflected well that reflects the last transaction but not the most recent one it's not instantaneous so yeah there it's gone through now so we can check it that should be zero great and our wallet balance should have the remaining i forget how much was left like uh i think it was 100 tokens or something like that so yep that's been incremented back up all right let's just try a few simple set things so we did one minute before let's try you know setting it to five minutes set lock time confirm that and i'll try another transaction to set the withdrawal amount so we started with 50 50 tokens let's change it to 25 just something that's easy to see all right so let's check these let's check um was the first one we did set what's your all amount that's this one right here uh that one hasn't gone through yet let's check the lock time 300 seconds that's five minutes perfect and i didn't see if the second one is updated yet set withdrawal amount and that's been updated to 25 tokens perfect so at this point it looks like everything is working great with the faucet we're able to test the um request request token function the withdrawal function we were able to test a lot of the conditions around those regarding permissions and only owner we were able to get the balance of the contract we're able to reset the log time reset the withdrawal amount and that concludes the testing for this contract all right well i appreciate you guys checking out this video i may follow this one up with a sort of a faucet d app tutorial short you know web3 kind of ui tutorial to tie this one up but other than that yeah appreciate it if you guys like this kind of content you want to see more about blockchain and defy web3 and all that kind of good stuff uh definitely encourage you to subscribe to the channel and uh until then i will catch you next time take care guys bye
Info
Channel: Block Explorer
Views: 13,912
Rating: undefined out of 5
Keywords: smart contract tutorial, solidity tutorial, faucet smart contract, faucet contract, erc20 faucet, erc20 tutorial, solidity interfaces, solidity events, Remix tutorial, Ethereum tutorial, erc-20 tutorial, erc-20 faucet, smart contract project, blockchain tutorial, hardhat tutorial, hardhat deploy smart contract, deploy smart contract, block.timestamp, solidity time, solidity rate limiting, ethereum goerli, ethereum faucet, faucet smart contract tutorial, token faucet
Id: jKW_0PQuIQw
Channel Id: undefined
Length: 47min 52sec (2872 seconds)
Published: Sat Sep 17 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.