In Solidity, access modifiers are the keywords to decide the level of access provided over variables and functions in a smart contract. Access modifiers can only restrict access to other contracts, but we should keep in mind that all the data on the blockchain can be viewed publicly.
There are four types of access modifiers available in Solidity.
Private: It is used to grant access only within a contract.
Internal: It is used to grant access within the contract and all the contracts that inherit it.
External: It is used to grant access only outside of the contract.
We can’t access the external function within our contract. However, they can be accessed using this.function()
.
Public: It is used to grant access within the contract as well as outside of the contract.
While specifying the access modifiers, we should choose the one that provides least access while fulfilling our requirements. Giving more access than required can not only be exploited but also results in code being less efficient. For example, using public costs more than external. So, we should opt for the modifier nearest to the top of the following pyramid.
In Solidity, access modifiers on variables are specified as:
<data-type> <access-modifier> <variable-name>;
Access modifiers can only be used on
The external modifier can’t be used on variables.
Let’s look at the following code:
pragma solidity ^0.5.0;contract SpecialNumbers{uint private num1;uint internal num2;uint public num3;constructor () public{num1=5;num2=10;num3=15;}}contract MyNumber is SpecialNumbers{function getNumber()public view returns (uint num){return num2+num3;}}contract OtherContract{function getNumber()public returns (uint num){SpecialNumbers Obj=new SpecialNumbers();return Obj.num3();}}
Line 4: We declare num1
as private.
Line 8: We can only use the variable declared in line 4 within SpecialNumbers.
Line 5: We declare num2
as internal.
Line 9: We can use the variable declared in line 5 in SpecialNumbers.
Line 16: We can also use the variable declared in line 5 within MyNumber
that inherits SpecialNumbers
.
Line 6: We declare num3
as public.
Line 10: We can use the variable declared in line 6 in SpecialNumbers
.
Line 16: We can also use the variable declared in line 6 within MyNumber
that inherits SpecialNumbers
.
Line 23: We can only use the variable declared in line 6 in OtherContract
.
In Solidity, access modifiers on functions are specified as:
function <function-name> (<list of parameters>) <access-modifier> {<body>}
Let’s look at the following code:
pragma solidity ^0.5.0;contract SpecialNumbers{uint private num1;uint internal num2;uint public num3;constructor () public{num1=5;num2=10;num3=15;}function getNum1()private view returns (uint num){return num1;}function getNum2()internal view returns (uint num){return num2;}function getNum3()external view returns (uint num){return num3;}function getNum()public view returns (uint num){return getNum1()+getNum2()+this.getNum3()+getNum();}}contract MyNumber is SpecialNumbers{function getNumber()public view returns (uint num){return getNum2()+this.getNum3()+getNum();}}contract OtherContract{function getNumber()public returns (uint num){SpecialNumbers Obj=new SpecialNumbers();return Obj.getNum3()+Obj.getNum();}}
Line 11: We declare getNum1()
as private.
Line 21: We can only call getNum1()
within SpecialNumbers
.
Line 14: We declare getNum2()
as internal.
Line 21: We can call getNum2()
within SpecialNumbers
.
Line 26: We can also call getNum2()
in MyNumber
, that inherits SpecialNumbers
.
Line 17: We declare getNum3()
as external.
Line 32: We can call getNum3()
in OtherContract
.
Line 21: We can call getNum3()
in MyNumber
by this.getNum3()
.
Line 26: We can call getNum3()
in SpecialNumbers
by this.getNum3()
.
Line 20: We declare getNum()
as public.
Line 21: We can call getNum()
within SpecialNumbers
.
Line 26: We can also call getNum()
in MyNumber
, that inherits SpecialNumbers
.
Line 32: We can also call getNum()
in OtherContract
.