Skip to Content

Inheritance and Modifiers

Let’s start with a simple token-like Smart Contract. Mind, this is not an ERC20 Token contract. Its much simpler than that, and this code sample is only here to demonstrate how modifiers and inheritance works!

View the Full Course Now 

Copy the following contract over to Remix to follow along

//SPDX-License-Identifier: MIT pragma solidity ^0.8.16; contract InheritanceModifierExample { mapping(address => uint) public tokenBalance; address owner; uint tokenPrice = 1 ether; constructor() { owner = msg.sender; tokenBalance[owner] = 100; } function createNewToken() public { require(msg.sender == owner, "You are not allowed"); tokenBalance[owner]++; } function burnToken() public { require(msg.sender == owner, "You are not allowed"); tokenBalance[owner]--; } function purchaseToken() public payable { require((tokenBalance[owner] * tokenPrice) / msg.value > 0, "not enough tokens"); tokenBalance[owner] -= msg.value / tokenPrice; tokenBalance[msg.sender] += msg.value / tokenPrice; } function sendToken(address _to, uint _amount) public { require(tokenBalance[msg.sender] >= _amount, "Not enough tokens"); tokenBalance[msg.sender] -= _amount; tokenBalance[_to] += _amount; } }

ethereum-blockchain-developer-image

Try the Smart Contract

What does the contract do? Let’s give it a try! Head over to the Deploy and Run Transactions tab.

  1. Select Account#1 from the Accounts Dropdown
  2. Deploy the Contract

ethereum-blockchain-developer-image

Buy Tokens

  1. Switch over to Account #2
  2. Enter 1 into the value field
  3. Select ā€œEtherā€ from the Dropdown
  4. Buy 1 Token for 1 Ether by hitting the purchase button

ethereum-blockchain-developer-image

Get the Token Balance

Now lets look if you have the right balance. Copy your address, fill it into the input field for ā€œtokenBalanceā€ and see if the balance is 1:

ethereum-blockchain-developer-image

Burn Tokens

Now lets see what happens if you stay on Account#2 and try to burn tokens:

  1. Try to burn with Account #2
  2. Observe the Error message
  3. Which is coming from the require statement

ethereum-blockchain-developer-image

Problem

Right now we have several similar require statements. They are all testing if a specific address called the smart contract. To avoid code duplication and make it easier to change this from a single place, we can use modifiers:

//other code modifier onlyOnwer { require(msg.sender == owner, "You are not allowed"); _; } //...

Let’s add this to the contract…

Adding A Simple Solidity Modifier

Now that you know whats the purpose of a modifier, let’s add a simple modifier and remove the code duplication:

//SPDX-License-Identifier: MIT pragma solidity ^0.8.16; contract InheritanceModifierExample { mapping(address => uint) public tokenBalance; address owner; uint tokenPrice = 1 ether; constructor() { owner = msg.sender; tokenBalance[owner] = 100; } modifier onlyOwner() { require(msg.sender == owner, "You are not allowed"); _; } function createNewToken() public onlyOwner { tokenBalance[owner]++; } function burnToken() public onlyOwner { tokenBalance[owner]--; } function purchaseToken() public payable { require((tokenBalance[owner] * tokenPrice) / msg.value > 0, "not enough tokens"); tokenBalance[owner] -= msg.value / tokenPrice; tokenBalance[msg.sender] += msg.value / tokenPrice; } function sendToken(address _to, uint _amount) public { require(tokenBalance[msg.sender] >= _amount, "Not enough tokens"); tokenBalance[msg.sender] -= _amount; tokenBalance[_to] += _amount; } }

Re-Deploy the Smart Contract and Test

  1. Deploy the Contract with Account#1
  2. Purchase Tokens with Account#2
  3. Try to Burn with Account#2

It should error out.

ethereum-blockchain-developer-image

Problem

Right now, we’re doing two things in one Smart Contract:

The token logic and the owner functionality.

We can further simplify the Smart Contract by using an Owner Smart Contract and then extending the Functionality. Let’s do that next…

Inhertiance with Solidity

Now its time to split up our Smart Contract into smaller pieces. We are going to do one Smart Contract that manages the ownership, and another one that does the Token logic:

//SPDX-License-Identifier: MIT pragma solidity ^0.8.16; contract Owned { address owner; constructor() { owner = msg.sender; } modifier onlyOwner() { require(msg.sender == owner, "You are not allowed"); _; } } contract InheritanceModifierExample is Owned { mapping(address => uint) public tokenBalance; uint tokenPrice = 1 ether; constructor() { tokenBalance[owner] = 100; } function createNewToken() public onlyOwner { tokenBalance[owner]++; } function burnToken() public onlyOwner { tokenBalance[owner]--; } function purchaseToken() public payable { require((tokenBalance[owner] * tokenPrice) / msg.value > 0, "not enough tokens"); tokenBalance[owner] -= msg.value / tokenPrice; tokenBalance[msg.sender] += msg.value / tokenPrice; } function sendToken(address _to, uint _amount) public { require(tokenBalance[msg.sender] >= _amount, "Not enough tokens"); assert(tokenBalance[_to] + _amount >= tokenBalance[_to]); assert(tokenBalance[msg.sender] - _amount <= tokenBalance[msg.sender]); tokenBalance[msg.sender] -= _amount; tokenBalance[_to] += _amount; } }

You see, now we have two contracts in one file.

Multiple Contracts in One File

Be careful when compiling and deploying the contract to select the correct one from the dropdown: ethereum-blockchain-developer-image

Of course, its not ideal to have multiple contracts in one file. That’s why we can also separate them and import contracts. Let’s do that next!

Importing Solidity Contracts

One great feature of Solidity is the ability to import contracts into other contracts.

Github Imports

Did you know? In Remix you can also directly import contracts from github repositories

Let’s take the previous contract and split it up into two separate files:

Ownable.sol Token.sol

Create these two files in Remix and copy the following content into the files:

//SPDX-License-Identifier: MIT pragma solidity ^0.8.16; contract Owned { address owner; constructor() { owner = msg.sender; } modifier onlyOwner() { require(msg.sender == owner, "You are not allowed"); _; } }

Let’s test this and head over to the Run Tab. You will see again several contracts in the dropdown.

If you select ā€œTokenā€ from the dropdown and deploy it, you’ll get the same contract as in the beginning, but better:

  1. The Contracts are split up into smaller logical units
  2. With modifiers we have re-usable small components we can also use in contracts extending the base contract
  3. With separate files we created a better organization of code

ethereum-blockchain-developer-image

Now, let’s have a look what happens here behind the scenes!

Last updated on