Modifiers & Inheritance & Import
Modifiers
are a great way to check pre-conditions.
//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 allowed");
tokenBalance[owner]--;
}
}
Both functions burnToken() and createNewToken() have the same require statement. We can centralize this by using a modifier instead.
modifier onlyOwner() {
require(msg.sender == owner, "You are not the owner");
_;
}
// needs to end with _;
//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;
}
modifier onlyOwner() {
require(msg.sender == owner, "You are not the owner");
_;
}
function createNewToken() public onlyOwner {
tokenBalance[owner]++;
}
function burnToken() public onlyOwner {
tokenBalance[owner]--;
}
}
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.
Import & Inherit
//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");
_;
}
}
https://ethereum.stackexchange.com/questions/92265/solidity-proper-way-to-import-contracts
both functions and state variables will be available
With the
is
case, the contract inherits all the functionality of the base contract.It means that when you instantiate the contract, a single object code (i.e., a single contract instance) containing all of that functionality is deployed on the network. Any call to a function of the base contract yields a non-external function call.
Import only (no inheritance)
Factory pattern -> used to deploy instances of a contract via new keyword
importing a contract into another so that you can use its instances in the contract you are importing it in
With the
has
case, the contract only holds a pointer to the other contract. They are essentially two different instances deployed on two different address on the network. Any call to a function of the other contract yields an external function call.
Other import stuff
Last updated