What is restricted access in Solidity?

Share

Overview

It is impossible to ensure perfect anonymity for our contract due to the public nature of the blockchain. Because everything on the blockchain is publicly viewable, we won’t be able to prevent someone from seeing the status of our contract from the blockchain. We can limit other contracts’ read access to the state of our contract. We can declare the state variables as private to achieve this. Functions can also be marked private, however this prevents anyone outside the contract scope from invoking them under any circumstances. On the other hand, declaring them public would give everyone on the network access.

Applicability

Where can this be applied?

  • Contract functions should only be called under specific situations.
  • When we want to apply similar constraints to a number of functions.
  • We want to make smart contract more secure against illegal access.

Implementation

The Guard Check pattern is used to implement the access restriction pattern. After a function is called, the Guard Check pattern checks for needed conditions and throws an exception if they are not fulfilled. Others argue that the tests should be performed prior to the commencement of the relevant function. Because these tests are generally duplicated over numerous methods, we advocate outsourcing the task to modifiers, which can then be applied to the functions that require it. Modifiers can take their own arguments, accept arguments from the function’s input parameters, or have the condition hard-coded in its body, which limits their reusability.

Example

pragma solidity ^0.5.0;
contract AccessRestriction {
address public owner = msg.sender;
uint public lastOwnerChange = now;
modifier onlyBy(address _account) {
require(msg.sender == _account);
_;
}
modifier onlyAfter(uint _time) {
require(now >= _time);
_;
}
modifier costs(uint _amount) {
require(msg.value >= _amount);
_;
if (msg.value > _amount) {
msg.sender.transfer(msg.value - _amount);
}
}
function changeOwner(address _newOwner) public onlyBy(owner) {
owner = _newOwner;
}
function buyContract() public payable onlyAfter(lastOwnerChange + 4 weeks) costs(1 ether) {
owner = msg.sender;
lastOwnerChange = now;
}
}

Explanation

  • Lines 5-6: The state variables owner and lastOwnerChange are populated with the contract creator and the current timestamp at contract creation time.

  • Line 8: The first modifier onlyBy(address _account) is attached to the changeOwner(…) function.

  • Line 26: We ensure that the function’s initiator (msg.sender) is equivalent to the variable supplied in the modifier call, which in this instance is owner. When this modifier is used, an exception is thrown if the guarded function is called by someone other than the current owner.

  • Line 13: The second modifier, onlyAfter(uint _time), is similar to the first, except that it throws an exception if the function to which it is connected is called before the specified time.

  • Line 30: It is given with the period of the last change of ownership plus four weeks and is utilized. (Four weeks are added instead of one month because Solidity does not support months as a unit of time.). As a result, the function call can only be successful if it has been at least four weeks since the last update.

  • Line 18: Before going into the execution of the guarded function, the third and final modifier costs(uint _amount) accepts an amount of money as input and ensures that the value given with the calling transaction is at least as high as the stated amount.

  • Line 20: This modifier is different from others it includes code that is executed after the function is called, which is triggered by the underscore .

  • Line 21: Extra if-clause checks if more money was supplied in the transaction than was required and returns the excess to the sender. This is an excellent illustration of the different options that modifiers may give.

  • When used in conjunction with the previous modification, the contract can only be purchased by a new owner four weeks after the last change in ownership and if the transaction involves at least one ether.
  • Line 30: To receive money with a transaction, the payable modification of the buyContract() method is required.