By Gary simon - Oct 27, 2017
The following tutorial is a part of our 100% free course: Developing Ethereum Smart Contracts for Beginners
In the previous lesson, we learned how to create Events. In this video, we're going to learn how to work with something as equally as important, which are function modifiers.
A modifier allows you to control the behavior of your smart contract functions. It includes a variety of use cases, such as restricting who has the ability to run a given function, unlocking functions at a certain time frame, etc..
In our case, we will create a modifier that allows only the contract owner to run a given function. In the context of our project, this will mean only allowing the contract owner to access the setInstructor() function.
Let's get started..
Be sure to Subscribe to the Official Coursetro Youtube Channel for more videos.
This tutorial is based on a course, where we have been working on a smart contract from previous lessons.
If you're hopping in out of the blue, this is the smart contract that you should copy and paste into the Remix IDE:
pragma solidity ^0.4.18;
contract Coursetro {
string fName;
uint age;
event Instructor(
string name,
uint age
);
function setInstructor(string _fName, uint _age) public {
fName = _fName;
age = _age;
Instructor(_fName, _age);
}
function getInstructor() view public returns (string, uint) {
return (fName, age);
}
}
Function modifiers in smart contracts can be used for a variety of purposes. For our purpose, we're going to create a modifier that will only allow the owner of the contract to set the instructor name and age through the setInstructor() function.
To do this, we first have to define a new variable as a type of address:
contract Coursetro {
string fName;
uint age;
address owner; // Add this
// Other stuff removed for brevity
Next, we have to call the constructor method in order to set the owner variable to the address that created the contract.
The constructor function is called only once, which is when the contract is first created:
contract Coursetro {
string fName;
uint age;
address owner;
function Coursetro() public { // Add this constructor
owner = msg.sender;
}
Great, now that we know owner contains the contract creator's address, let's create a modifier beneath the constructor:
modifier onlyOwner {
require(msg.sender == owner);
_;
}
So, to create a modifier, you first start by stating modifier and the name of the modifier. In our case, it will be onlyOwner which can be used multiple times as a modifier depending on your needs.
Note: Modifiers can also receive arguments, ie: modifier name(arg1)
Inside of our modifier, we're saying require() which is a way of saying, "if the condition is not true, throw an exception".
If the condition is true, _; on the line beneath is where the function body is placed. In other words, the function will be executed.
We've created a modifier, now what? Well, we can use it in any function where we only want the smart contract creator to have access.
Let's add it to the setInstructor() function:
function setInstructor(string _fName, uint _age) onlyOwner public {
fName = _fName;
age = _age;
Instructor(_fName, _age);
}
Notice onlyOwner is specified just after the arguments of the function. That's all it takes!
If you want to give it a go in the Remix IDE, click the Create button to create the contract. Then, specify "Gary", 44 in the setInstructor function textfield on the right of the IDE and click on the function name to set it.
It should work, and to verify, click getInstructor.
Now, try changing the Account dropdown at the top to a different account than the one used to create the smart contract and repeat the process above.
You'll notice it won't work this time, the debugger will throw an error.
We have been creating a Web3 UI to interact with our smart contract. If you're just hopping in during this 5th lesson, you can take this course for free and have access to the project files which contains our coding up to this point.
Before we continue, being that we've updated the smart contract and recreated it in Remix, we need to grab the ABI from Compile -> Details and paste it into the web3.eth.contract() method in our project, as well as copying the smart contract address and pasting it into the CoursetroContract.at('') method.
After updating the project, you can load up index.html in the browser and assuming web3.eth.accounts[0] is being used for the defaultAccount, the UI should let you update the instructor name and age, being that you're using the owners account.
If you try changing the defaultAccount to web3.eth.accounts[2] for instance, you will see it won't let you update the account. In fact, the rotating spinner will spin forever. Ugh, that's not what we want. If you look at the inspector in Chrome, you will find a big red error.
We need to adjust our Coursetro.setInstructor function in the JavaScript to provide for a better experience:
// Previous code
Coursetro.setInstructor($("#name").val(), $("#age").val()
// Change ^-that to this:
Coursetro.setInstructor($("#name").val(), $("#age").val(), (err, res) => {
if (err) {
$("#loader").hide();
console.log('oh no');
}
});
As you can see, we're passing in a callback function, which Web3 providers, and we're checking if an error err was returned, then to hide the loader graphic and console log 'oh no'. Typically, you would do something other than console log, but you get the point.
Refresh the page and give it a shot now with the incorrect account. It will show the oh no log, but it won't leave the spinner sitting.
Wow, we've progressed quite a bit so far in this course! By now, you should have a pretty good understanding of most of the basic concepts associated with Ethereum smart contract development.
We're not done yet, in fact, we have quite a bit more to learn.