(Part 4) Ethereum Solidity Development - Inheritance,Working With Multiple Contracts And Simple Mutability(PT 4)

in #utopian-io6 years ago

Repository

https://github.com/igormuba/EthereumSolidityClasses/tree/master/part3

What Will I Learn?

  • Inheritance
  • Multiple children with their own inherited variable
  • Multiple children changing the parent variable
  • Mutability by address

Requirements

  • Internet connection
  • Code editor
  • Browser

Difficulty

  • Intermediate

Tutorial Contents

If you get to work on a big project, or you check a big project Solidity code on Github, you will notice that they have multiple contracts working to achieve one application, I will introduce you to how to get started with working with multiple contracts.
If you don't yet follow this tutorial series, I recommend you to read my previous class on contract mutability (don't worry, I don't use assembly code) and delegatecall
https://steemit.com/utopian-io/@igormuba/part-3-ethereum-solidity-development-contract-mutability-delegatecall-and-calling-functions-by-address-pt-3
This might add up to your skill set and will probably come handy when working with multiple contracts

Inheritance in solidity

You can easily achieve inheritance by using the is keyword.
When you inherit another solidity contract the new contract will copy and create it's own variables similar to the ones from the parent contract. Here is a practical example on how does that work, you can do the following on a single .sol file or multiple files, and you only need to compile and run the contract you want to use, that is, don't need to compile the parent!

pragma solidity ^0.5.0;

//parent contract
contract one{
    uint internal myVariable;//non initiated variable
//I will talk about the internal vs private vs public a bit later in this tutorial
}

//child contract
contract two is one{
    function sumToOne() public{
        myVariable++; //when you call this function the myVariable from the child
//increases by one
    }
    
    function getOne() public view returns(uint){
        return myVariable;//when you call this function you get the value
//of the variable from this child
    }
}

//third child, works exactly like the previous child
//but has it's own variables detached from the other contracts
contract three is one{
    function sumToTwo() public{
        myVariable++;
    }
    function getTwo() public view returns(uint){
        return myVariable;
    }
}

Using the example above we can compile directly the third contract, without compiling the previous 2 and it will still work as expected
I have clicked the sumToTwo on the third contract 3 times and it shows 3

If now I compile and run the second contract, the first child, you can notice that changing it's variables do not affect the other child

I have clicked the sum button on the contract two, then retrieved it's variable, and retrieved the one from the third again to make sure they do not interact.

As you can notice, they are all standalone and independent contract from one another!

Internal, external, public and private meaning

  • public: anyone anywhere can access it
  • **private: ** only the contract itself can access it, children and external ones not
  • external:only external source can access it, the contract itself can not, not used very often
  • internal: only the contract and it's children can access it

Making the child change the parent variables

Ok, just like on the previous tutorial, we are getting to the difficult part. You see, Solidity has emphasis on security and privacy, just like it was not designed to allow a contract to be changed but we can hack it into allowing mutability, it was neither designed to allow contracts to change each other's variable, but we can do it if we use some clever tricks

pragma solidity ^0.5.0;


contract one{//the contract where the variables will be
//externally changed
    uint myVariable; //variable to be changed externally
    function initiateMyVariable(uint number) public {//function to change the variable
        myVariable=number;
    }
    function getMyVariable() public view returns (uint){//function to retrieve the variable
        return myVariable;
    }
}

//contract that will change the variables from the contract one
contract two{

//this stores the interface of a contract of type one
    one public contractOne; //1 see on notes below the code
    
//to avoid bugs we deploy this with the address of a contract of type one
    constructor(address oneAddress) public{
//2 see notes below the code
        contractOne = one(oneAddress);//tells which contract of type one we are talking about
//if you saw last tutorial you might have some ideas of
//how to achieve mutability easier with this ;)
    }
    
    function setOneAddress(address oneAddress) public{
//allows us to change to another contract of type one
        contractOne = one(oneAddress); //2 see notes below the code
    }
    
    function initiateOneVariable(uint number) public{
//sets the varaible of the contract linked
        contractOne.initiateMyVariable(number);
    }
    
    function addToOneVariable(uint number) public{
//retrieves the variable from the contract linked
//and turns it into itself plus the number we gave to add
        contractOne.initiateMyVariable(contractOne.getMyVariable()+number);
    }
    
    function getOneVariable() public view returns (uint){
//returns the variable from contract of type one linked
        contractOne.getMyVariable();
    }
}

So, based on the code above, the core pieces you must keep in mind when accessing functions from another contract are (check notes with numbers on the code)

  • 1 initiate a variable with the type of the contract
  • 2 give that variable the address of a contract of same type as the variable

Because on the Ethereum blockchain there can be thousands of contracts with the same name and type, so it is important to not just specify the type, but which EXACT contract of that type we want to access, anything that does not comply with those 2 requirements will throw an error because there is no way for the Ethereum to find which contract you are actually talking about

A new technique to achieve mutability

If you saw on the last tutorial
https://steemit.com/utopian-io/@igormuba/part-3-ethereum-solidity-development-contract-mutability-delegatecall-and-calling-functions-by-address-pt-3#@utopian-io/re-part-3-ethereum-solidity-development-contract-mutability-delegatecall-and-calling-functions-by-address-pt-3-20190102t220817z

I have taught a lower level way to achieve mutability, the way we did before was storing the variables on the main contract and using functions from other contract to do it.

Using what we have learned on this tutorial here we can, more easily, achieve a similar result!

Let us test with a code similar to the the code we have used in the last section but changed to do math instead

pragma solidity ^0.5.0;


contract one{
    uint total;
    
    function doMath(uint number1, uint number2) public {
        total = number1+number2;
    }
    
    function getTotal() public view returns (uint){
        return total;
    }
}

contract two{
    one public contractOne;
    
    constructor(address oneAddress) public{
        contractOne = one(oneAddress);
    }
    
    function setOneAddress(address oneAddress) public{
        contractOne = one(oneAddress);
    }
    
    function delegateMath(uint number1, uint number2) public{
        contractOne.doMath(number1, number2);
    }
    
    
    function getOneTotal() public view returns (uint){
        return contractOne.getTotal();
    }
}

Using the example above, here is what we can do


Deploy the contract one and copy it's address


Deploy contract two passing the one address as argument

Now if you do math you will be using whatever logic is inside the contract one, in this case, it sums the numbers passed to it as arguments.

But if we change the address of the contract type one that is stored inside the contract two we can use another mathematical operation!

Change the contract one to multiply the arguments passed into it, deploy it again and give it's address to the contract two



When you do the math again again you will see that the result changed according to the new math operation! And you can change it back and forth!

Difference between delegatecall and address mutable contracts

So, on the previous class I taught a more lower level of deploying mutable contracts and in this one a more "modern" way to do it, what are the differences between them?

The main difference is that by using delegatecall you will be calling a function from another contract and executing it completely on the context of the caller, it will work as it if were a function written on the caller contract!

In the example I taught today the called function will be executed in the context of the callee contract, which by itself also allows you to add even more functionality and new variables.

If you plan on having a simple contract and avoid creating new code and new variables and new functions, the method from the other tutorial might suit you better

If you want your contract to be easily upgraded and allow yourself to add more functionality in the future, the technique I taught you today might suit you better. Just keep in mind CONTRACTS SHOULD NOT BE DESIGNED TO MUTABLE!

Curriculum

I AM A STEEM WITNESS

To vote for me, simply use the SteemConnect link below
https://steemconnect.com/sign/account-witness-vote?witness=igormuba&approve=1

or go to https://steemit.com/~witnesses

(note, it is /~witnesses, not /witness)
Scroll all the way down to "If you would like to vote for a witness outside of the top 100, enter the account name below to cast a vote."

type igormuba and click vote

Sort:  

Thank you for your contribution @igormuba.
After analyzing your tutorial we suggest only one point:

  • The comments in the code are very important, but I think you've put too many comments and extended ones. The comments are usually small but intuitive so that the user understands what you will do.

Again, good work on developing your tutorial. It is very well explained and intuitive.

We are waiting for your next tutorial.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]

Thank you for the review, you have helped me improve a lot on the tutorials, your work is appreciated very much

Posted using Partiko Android

Thank you for your review, @portugalcoin! Keep up the good work!

Congratulations @igormuba! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :

You received more than 500 as payout for your posts. Your next target is to reach a total payout of 1000

Click here to view your Board
If you no longer want to receive notifications, reply to this comment with the word STOP

To support your work, I also upvoted your post!

Support SteemitBoard's project! Vote for its witness and get one more award!

Hi @igormuba!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server

Hey, @igormuba!

Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!

Coin Marketplace

STEEM 0.20
TRX 0.13
JST 0.030
BTC 66976.31
ETH 3509.07
USDT 1.00
SBD 2.70