Inheritance Assignment

Hi @mickymax777,

That’s the correct modification to HelloWorld so that it inherits from the new separate contract, Destroyable.

Can we also see your code for Destroyable.sol? That’s the main part of this assignment.

Nice solution @alegarap :ok_hand:

What changes did you also have to make to HelloWorld in terms of inheritance?

1 Like
Destroyable.sol

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

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

I created a new contract (screenshot):

I added in the Hello World contract the DestroyContract contract

@ Filip
First I created the selfdestruct(owner); But solidity gave me this. I don’t understand because the owner variable is linked to an address?

1 Like

Exactly right, @Ouzo69 :+1:

Excellently presented solution, and well done for realising that, by using owner instead of msg.sender as the selfdestruct function’s argument, you needed to make owner a payable address :+1:

I also noticed your very clever (and much more concise) alternative to the withdrawAll() function — impressive stuff :muscle: :smiley:

1 Like

Hi @sajede.k,

When our derived contract HelloWorld (or in your case, contract map) is deployed, there is only one contract that is deployed, not three separate ones. The fact that we have written 3 contracts related to each other via inheritance, is purely a way of organising our code so that it is more modular and easier to maintain and develop further. The single HelloWorld contract that is deployed includes all of the inherited functionality of Ownable and Destroyable, as if this had been written within HelloWorld itself. So when HelloWorld is deployed and selfdestruct() is invoked, even though selfdestruct is physically written in Destroyable, practically, it’s as if it is being called within HelloWorld, and that’s the key to how it knows which contract to destroy.

Remember that all functions, state variables, mappings, events, modifiers and constructors are inherited with the exception of functions, state variables and mappings marked with private or external visibility.

1 Like

Hi @Nicksta,

Your DestroyContract inherits Owner, and so (providing you haven’t made any additional modifications to Owner) the state variable  address public owner   will automatically be available within DestroyContract — you don’t need to repeat it.

Everything else is correct :ok_hand:

To understand this error, you first need to understand that addresses can be stored in variables as either payable, or non-payable. Unless we specifically mark them as payable, then they are non-payable by default.

The address argument passed to the selfdestruct function must be payable, because it is used to transfer the contract balance to that address. It works with msg.sender, because if used directly as a value (and not first assigned to a variable) then msg.sender is treated as a payable address by default in Solidity. You get the error with owner because this is defined as a non-payable address in contract Owner. To define an address as payable, you need to explicitly add the payable keyword:

address payable public owner;

If you make this modification to the owner state variable definition in Owner, then it will work calling selfdestruct with owner, as follows:

selfdestruct(owner);

Another alternative is to leave the owner state variable definition as non-payable, and convert it to a payable address directly within the selfdestruct function call in DestroyContract:

selfdestruct(address(uint160(owner)));

By the way, that’s fine to post a screen shot to show an error message, but please don’t post screen shots of your submitted code, because it’s not possible to copy and paste it in order to execute and test it, if necessary. It also can’t be quoted. In future, please post your code formatted in the usual way :slight_smile:

I hope that’s clarified things for you. Just let us know if you have any further questions.

1 Like

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

contract Destroyable is Ownable {

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

}

1 Like

quick response!! Thanks a lot!! :muscle: :muscle:

1 Like

Here is my Destroyable contract:

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

contract Destroyable is Ownable {

function destroyContract() public onlyOwner{
    selfdestruct(address(uint160(owner)));
}

}

And here is the new header for my main contract:

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

contract mappingPractice is Ownable, Destroyable{

I got a compiler error regarding my Owner address in the selfdestruct(owner) function, so I used address(uint160()) to convert it into a payable address and it seemed to work fine after that.

1 Like

//Ownable.sol
pragma solidity 0.5.12;
contract Ownable{

address payable public owner;

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

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

}

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

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

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

contract HelloWorld is Ownable, Destroyable{

1 Like

This is my code if I didn’t have a separate Ownable contract:

pragma solidity 0.5.12;

contract Destroyable {

address public owner;

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

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

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

}

then add to the top of HelloWorld contract : import “./Destroyable.sol”;

Hello,
thanks a lot for taking time.

1 Like

Hello @MrSeven , hope you are great.

Now a few comments on your code:

Meaning, your close function ask for a argument (address) that is never used in the function, this will trigger an error.

I advice to follow the video lesson closely, create your own Ownable contract has filip goes, if not, you might run into many issues later in the course without a way to compare with filip lessons.

If you have any more questions, please let us know so we can help you! :slight_smile:

Carlos Z.

1 Like

I get an error with this code.


pragma solidity 0.5.1;

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

Hello @oneworldcoder, hope you are good.

Your Destroyable contract is Ownable, but you are not importing the Ownable contract into your code. Maybe you want to check the video lesson again, it is important to understand those kind of little details.

If you have any more questions, please let us know so we can help you! :slight_smile:

Carlos Z.

2 Likes

Create the Destroyable.sol contract and called it from Hello_World.sol

import "./00_Ownable.sol";
import "./00_Destroyable.sol";
pragma solidity 0.5.12;

contract HelloWorld is Ownable, Destroyable{..}

The Destroyable.sol fil is:

import "./00_Ownable.sol";
pragma solidity 0.5.12;

contract Destroyable is Ownable{
    function close() public onlyOwner {     // onlyOwner is custom modifier
        selfdestruct(msg.sender);    
    }
}

I will check why I couldn’t only use owner variable directly, and only run by using msg.sender

selfdestruct(owner);

EDITED: I’ve got it from solution video. owner is not payable, so I need it to change it before.

1 Like

Hey @oneworldcoder,

As well as the point that @thecil makes:

… you may find that you still get an error with owner as the argument in the selfdestruct function call. If you do, it’s because owner is defined as a non-payable address in contract Ownable:

address public owner;

Addresses can be stored in variables as either payable, or non-payable. Unless we specifically mark them as payable, then they are non-payable by default.

The address argument passed to the selfdestruct function must be payable, because it is used to transfer the contract balance to that address. It would work with msg.sender , because if used directly as a value (and not first assigned to a variable), then msg.sender is treated as a payable address by default in Solidity. To define an address as payable, you need to explicitly add the payable keyword:

address payable public owner;

I hope that helps you to understand another possible reason for the error you were getting.

2 Likes

Well done @josephg for finding the answer to your question :ok_hand:
That’s right — owner is defined as a non-payable address in contract Ownable:

address public owner;

Addresses can be stored in variables as either payable, or non-payable. Unless we specifically mark them as payable, then they are non-payable by default.

The address argument passed to the selfdestruct function must be payable, because it is used to transfer the contract balance to that address. It works with msg.sender , because if used directly as a value (and not first assigned to a variable), then msg.sender is treated as a payable address by default in Solidity. To define an address as payable, you need to explicitly add the payable keyword:

address payable public owner:

Also, take a look at this post — it explains how you can make an additional adjustment to HelloWorld in terms of the inheritance. I think you’ll find it interesting :slight_smile:

Thank you @jon_m

1 Like