Inheritance Assignment

Hi @iceman007!

Your solution is correct, but it involves making an additional change to contract Ownable. Do you know what it is and why?

In addition, have look at @firepol’s post just above, and my reply, and you will see that we can also make our inheritance code in HelloWorld more concise as well.

1 Like

Hi Jon

Yes I needed to make my owner as a payable address.

2 Likes

First I added this to Hello World:

import “./Ownable.sol”;
import “./Destroyable.sol”;
pragma solidity 0.5.12;

contract HelloWorld is Ownable, Destroyable{

I wondered if you could add multiple imports into one import command, but it did not seem to take, so I did it separately.

Then I created Destroyable.sol:
import “./Ownable.sol”;
pragma solidity 0.5.12;

contract Destroyable is Ownable{

function destroy() public onlyOwner{
address payable reciever = msg.sender;
selfdestruct(reciever);
}
}

I was having some issues with the self destruct at first, but I worked it out. Defining payable was the key in my case.

1 Like

Hi @DeCryptolorian,

Nice analysis of your steps, and thought processes :+1:

Check this post out — it explains how you can make an additional adjustment in terms of the inheritance. I think you’ll find it interesting.

1 Like
import "./Ownable.sol";
pragma solidity 0.6.8;

contract Destructable is Ownable {
    function destruct() public onlyOwner{
        selfdestruct(owner);
    }
}
pragma solidity 0.6.8;

contract Ownable
{
    address payable owner;
    
    constructor() public 
    {
        owner = msg.sender;
    }
    
    modifier onlyOwner()
    {
        require(msg.sender == owner);
        _;
    }
}
1 Like

Hi @matren,

Nice solution :ok_hand:

By the way, what amendments did you make to contract HelloWorld in terms of its inheritance?

I also noticed that in contract Ownable you didn’t state the visibility of

I’m interested to know if that was a deliberate decision? Your code still runs without it, but it would make the contract clearer for other developers if you stated what you intend the visibility to be.

1 Like

Thanks for asking.
You’re right, visibility should always be used to state the intend.

For now i don’t know which visibility to use in solidity.
In general i would use the most restricted visibilty possible. In this case it should be then “internal”.

The default visbility in solidity is “public” where other languages normaly use “private” as default.
There must be a reason why “public” was chosen in solidity as the default.

Some statements about this (please correct me if i am wrong):

  1. state variables can only be changed through a function call in the contract itself
    (meaning, it cannot be changed from external contracts or through the API exposure of the contract).

  2. state variables are visible in the blockchain, therefore there’s no way to hide their contents

So my question would be:
Is there any reason i should make the owner “internal” instead of defaulting it to “public” ?

If i see it correctly public state variables have a “public getter” but still an “internal setter”.

1 Like

In the Onwable contract I explicitly converted the owner address to an address payable, like so:

address payable internal owner; // Limit access.

Next, the Destroyable contract reads as such:

import "./ownable.sol";
pragma solidity 0.5.12;

contract Destroyable is Ownable {
    
    function close() public onlyOwner { 
        selfdestruct(owner);
    }      
    
}
1 Like

contract ownable{

address payable public owner;

modifier onlyOwner(){
    require(msg.sender == owner);
    _; //Continue execution
}
constructor() public{
    owner = msg.sender;
}   

}

contract destroyable is ownable{

function destroy() public onlyOwner {
    selfdestruct(owner);
}

}

contract HelloWorld is ownable, destroyable{

}

1 Like

I created a new Destroyable contract (which in fact derives from Ownable because only the owner should be able to destroy the contract):

import "./Ownable.sol";

pragma solidity 0.5.12;

contract Destroyable is Ownable {
    function close() public onlyOwner {
        selfdestruct(owner);
    }
}

Then I made our HelloWorld contract Destroyable (I initially inherited from Ownable and Destroyable but then realized that Destroyable was already Ownable :

contract HelloWorld is Destroyable {
    //...
}

Compiled, deployed and executed the close function:

[vm]from:0x147...c160cto:HelloWorld.close() 0x459...d8f30value:0 weidata:0x43d...726d6logs:0hash:0x178...4dce6
Debug
 status 	0x1 Transaction mined and execution succeed
...

I also needed to make the following change in the type of the ower variable of the Ownable contract:

address public owner;

changed to:

address payable public owner;

That’s because when destroying a contract, all it’s funds will be transferred to the owner’s address.

1 Like

pragma solidity 0.5.12;

import “./Ownable.sol”;

contract Destroy is Ownable{

    function  close () public onlyOwner{
        address payable count = address(uint160(owner)); 
        selfdestruct (count);
       }

}

1 Like

Hi @matren,

Sorry for the delay in replying. Great questions!

I’ve given them a lot of thought, and rather than intending my following comments to be a definitive answer, I see them more as throwing out some ideas for further debate. So I’m also tagging my colleague @gabba, to ask for his input.

That’s exactly what I would use here if you want to prevent the smart contract from automatically creating a public getter enabling the owner’s address to be viewed externally by an end user from their front-end application. That of course doesn’t prevent you from writing your own public getter function to provide this functionality. But I think the key thing here is that by setting the visibility to internal we at least give ourselves more control over our smart contract’s capabilities.

Good question! As you have said, my understanding is also that …

… and so private doesn’t actually mean secret here. Rather than being about data privacy, I think visibility is more about how many checks and balances we as developers build into the code of our smart contract. In other words, visibility provides developers with more or less control over which parts of their smart contract are more readily accessible from other functions and user interfaces, both internally and externally.

However, I’m not entirely convinced that, by omitting the visibility marker, Solidity defaults to full public visibility, because when we do this, Remix doesn’t automatically provide a getter for the owner’s address like it does when visibility is expressly marked public. But, as I’ve already mentioned above, even if we mark a state variable as private, we can always just access it anyway by writing our own public getter function. Again, this would seem to support my theory that the importance of visibility is to provide us with different degrees of control over our smart contract’s capabilities, and is therefore also an important tool in helping to reduce the risk of bugs creeping in. And I think these are the reasons I would give in answer to your question:

Essentially, this is correct. External contracts and front-end users can only manipulate state variables indirectly, by invoking functions marked with public visibility (or public or external visibility in the case of external contracts).

I think that whether you are getting or setting the value of a state variable as a front-end user, you are always calling a smart contract function, and so always accessing the variable’s value indirectly, rather than directly.

1 Like

Hi @Brandon,

Nice solution :ok_hand:

By the way, what amendments did you make to contract HelloWorld in terms of its inheritance?

1 Like

Hi @Jian_Hao_Wei,

Don’t forget to import the parent contracts at the top of your derived contracts. For your contracts you would need:

// Destroyable.sol
import "./Ownable.sol";
pragma solidity 0.5.12;

// HelloWorld.sol
import "./Ownable.sol";
import "./Destroyable.sol";
pragma solidity 0.5.12;

Also, check this post out — it explains how you can make an additional adjustment in terms of the inheritance. I think you’ll find it interesting.

2 Likes

The Ownable contract holds the owner logic for the HelloWorld contract:


pragma solidity 0.5.12;

contract Ownable {

    address public owner;
    
    constructor() public{
        owner = msg.sender;
    }

    modifier onlyOwner(){
        require(msg.sender == owner);
        _;
    }

}

The Destroyable contract inherits Ownable to be able to use its functionality, so that only the owner of the HelloWorld contract can execute the kill() function:


import"./ownable.sol";
pragma solidity 0.5.12;

contract Destroyable is Ownable {

    function kill() public onlyOwner{
        selfdestruct(msg.sender);
    }

}

The HelloWorld contract inherits the Ownable contract and the Destroyable contract to have access to their functionality:


import "./ownable.sol";
import "./destroyable.sol";
pragma solidity 0.5.12;

contract HelloWorld is Ownable, Destroyable{

}

1 Like

import “./Ownable.sol”;
pragma solidity 0.5.12;

contract Destroyable is Ownable {
function destroy() public onlyOwner {
address payable owner = msg.sender;
selfdestruct(owner);
}

}

1 Like

Hey @jon_m,

I imported the destroyable.sol file which contains the contract Destroyable decleration. I then amended the contract HelloWorld to inherit from contract Destroyable like so:

import "./ownable.sol";
import "./destroyable.sol";
pragma solidity 0.5.12;

contract HelloWorld is Ownable, Destroyable{
    ...
}
1 Like

I used multi-level inheritance to get this completed. I started with my parent contract “Ownable”:

pragma solidity 0.5.12;

contract Ownable{
address payable public owner;

constructor() public{
        owner= msg.sender;
    }   
modifier onlyOwner(){
        require(msg.sender == owner);
        _;
    }       

}

Then I created the “Destroyable” child contract:

import “./Ownable.sol”;

pragma solidity 0.5.12;

contract Destroyable is Ownable{

function close() public onlyOwner{
    selfdestruct(owner);
}

}

Finally I inherited the traits from the “Destroyable” parent contract into my “HelloWorld” contract.

1 Like

:ok_hand: @Brandon

Also, check this post out — it explains how you can make an additional adjustment in terms of the inheritance. I think you’ll find it interesting.

@jon_m,
Ha ha, even before I clicked the link, I realised I should have removed the is Ownable. The Ownable had been rendered redundant, since it’s included in Destroyable. doh!

1 Like