Modifier + Inheritance +Ownable

  • Modifiers are code that can be run before and / or after a function call.

  • Modifiers can be used to restrict access to certain functions or to enforce business logic. Here are some examples of how modifiers can be used.

Example

modifier onlyOwner() {
   require(msg.sender == owner, "Not owner");
   // Underscore is a special character only used inside
   // a function modifier and it tells Solidity to
   // execute the rest of the code.
   _;
}

If you are repeating a conditional check in multiple functions, it can be wrapped within a modifier for easy reuse.

//SPDX-License-Identifier: MIT
pragma solidity 0.8.3;

contract ModifierExample {

    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 the owner");
        tokenBalance[owner]++;
    }

    function burnToken() public {
        require(msg.sender == owner, "You are not the owner");
        tokenBalance[owner]--;
    }
}
  • Both functions burnToken() and createNewToken() have the same require statement. We can centralize this by using a modifier instead.

  • We can take this one step further by abstracting it with Inheritance.

Inheritance

Inherited contracts are deployed as a single contract, not seperate ones.

We shall move the owner variable and modifier into a separate contract called Owned. Our earlier contract will now inherit as per ModifierExample is Owned

//SPDX-License-Identifier: MIT
pragma solidity 0.8.3;

contract Owned {
    address owner;

    constructor() {
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "You are not the owner");
        _;
    }
}

contract ModifierExample 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]--;
    }
}

The derived contract is able to utilize the modifier onlyOwner defined in the parent as well as the owner variable which was set by the parent.

When contract A inherits from contract B, only contract A is actually deployed to the blockchain. All code from contract B is copied into contract A. So there is only one smart contract address.

Last updated