The Restricted Access Pattern in Solidity
The Restricted Access to a Contract is a common practice. By default, a contract state is read-only, unless it is specified as public. We can restrict who can modify the contract's state or call a contract's functions using modifiers.
For a better understanding of restricted access pattern we will build a contract with modified restricted access with the following common write outs:
We will create a contract called RestrictedAccess with two variables owner and creationTime, and we are going to initialize them. We will set the owner to be the owner of the contract (msg.sender) and for the creationTime we are going to use a global variable (block.timestamp).
Now, let's create a function that can change the owner of the contract and name it changeOwner. The function will take an address as an argument and call it _owner, and It should return owner = _owner.
What if we want to restrict the address of the changeOwner function? We don't want anyone to be able to change the owner address. We only want the current owner to change the owner's address. To do this we can use a modifier - onlyBy. We will name it onlyBy and it will take as input an address. The modifier have a requirement that the msg.sender should be equal to the input of the _account. If it fails, then we can write a statement "Sender not authorized!"
The onlyBy modifier requiring the only person with this modification that's going to be able to do whatever they want to do has to be msg.sender has to equal that for whatever the account is. If it is not coming from the current caller, then it is going to fail.
In order to add our modification we have to take onlyBy and add it to our changeOwner function, and if we want to restrict the access of onlyBy to the owner, then we can add the owner address.
This should work for the owner, because we sent the owner to the msg.sender. Next, let's test this. We deployed our contract on the first account. Now, let's move to the second account, copy and paste it in the changeOwner and run the function. We can see in the console that it doesn't work, we got an error - "Sender not authorized!"
It was not worked because we sent from the second account, not from msg.sender. If we do the same thing, we keep the same second account in function (changeOwner), but we switch back to our first account and and run changeOwner again we will se a successful transaction in the console - we have successfully changed the account now.
Now, if we try again, it is not going to work anymore immediately, because the msg.sender was changed to the second account and we are still in the first account which is not longer the owner. If we will switch to the second account and repeat, it will work.
Excellent! That is the onlyBy - a common pattern in #solidity for restricted access. Let's move forward and take a look at the onlyAfter modifier.
领英推荐
We will use the same contract. First of all we will write a function that can disown the current owner. Let's say we only want the owner to be able to delete himself, we don't want other people to be able to do this. After this we will use the onlyAfter modifier to set a time period for the function until it will run.
Now let's allow this function (disown) to be executed after a certain period of time (for example 3 weeks) from the moment of contract creation (we have a variable called creationTime which gives us the current time of the creation). For doing this we will create a new modifier (onlyAfter) which will take an uint as input and name it _time. For the require we will write that block.timestamp should be >= the amount of _time, otherwise, if it doesn't run, we will receive the message 'Function was called too early!'.
After creating this modifier, we need to add our 3 weeks for the function disown to be able to disown the owner. For doing this we need to write onlyAfter(creationTime + 3 weeks) in our disown function.
Let's deploy. You can see that if we try to disown, we are going to see that "Function was called too early!"
To see what will happen after the set time period we will change to 5 seconds and redeploy the contract.
Now it works!
An finally, let's see what the costs restriction! We will create a modifier called costs which takes an _amount parameter and require that msg.value is greater than or equal to the amount. If the msg.value is not greater than or equal to the amount, then return a string that says "Not enough Ether provided!".
Next we will write a payable function called forceOwnerChange which takes an address called _newOwner. The function needs 200 Ether to set the owner to the contract to the new owner of the address.
Congratulations! We covered all three restricted access modifiers.
I uploaded this code to my?GitHub account.
See you in the next articles about #smartcontracts , #solidity , #remix , #blockchaindeveloper #blockchaineducation #bitcointechnology #ethereumblockchain .