Inheritance Assignment

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

Hello, here’s my solution to the selfdestruct assignment. I tried it without the second line but it gives an error. Can someone explain why I had to go through the conversion part? Thanks.

1 Like

Nevermind, was explained in the solutions video already! :slight_smile:

1 Like

Hi @newavel,

I’m glad you had your question answered by the solution video :+1:

By the way, you may be interested to know that a more concise alternative (merging the 2nd and 3rd lines of code into just 1) is as follows:

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

This post explains why the solution video includes the additional step of saving owner or msg.sender to a local variable (in your solution, owner1 ), but how it isn’t actually necessary to do this.

Could we also see your complete code for Destroyable.sol? The rest is crucial for the inheritance to work correctly. The solution also involves a modification to HelloWorld in terms of inheritance.

1 Like
import "./Ownable.sol";
contract Destroyable is Ownable{
    
    function close() public onlyOwner { //onlyOwner is custom modifier
        selfdestruct(msg.sender);  // `owner` is the owners address
    }
}

To ensure only owner of contract could kill helloWorld contract, I Inherited Owned contract so contract Destroyable could use the onlyowner function.

1 Like

I got help by the document Filip shared and the Read The Docs website’s page

HelloWorld.sol:

import "./Destroyable.sol";
contract HelloWorld is Destroyable {
...

and in the file named: Destroyable.sol:

pragma solidity 0.5.12;

contract Destroyable {
    
    constructor() public { owner = msg.sender; }
    address payable owner;
    
    modifier onlyOwner {
        require(
            msg.sender == owner,
            "Only owner can call this function."
        );
        _;
    }
    
    function destroy() public onlyOwner { //onlyOwner is custom modifier
        selfdestruct(owner);  // `owner` is the owners address
    }
    
}
1 Like

Nice solution, @bjorkmanders :ok_hand:

For this to work, what changes did you also have to make to HelloWorld in terms of inheritance?

Nice work, @Atlas :ok_hand:

I also suggest separating out the functionality related to establishing the contract owner, from the functionality related to destroying the contract. I think that makes more sense than including them both within a contract named Destoyable.

I would also state the visibility of the state variable owner rather than omitting it. If you don’t want a public getter (displaying the owner’s address) to be automatically generated, you could mark it with internal visibility instead, ensuring that it is still available to the derived contracts.

1 Like

Destroyable.sol

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

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

HelloWorld.sol

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

contract HelloWorld is Destroyable{

1 Like
import "./Destroyable.sol";
contract HelloWorld is Ownable, Destroyable {

1 Like

You are right that you only need to import Destroyable.sol, because HelloWorld only needs to explicitly inherit contract Destroyable — it will indirectly inherit Ownable via Destroyable. So can you see that you can also remove Ownable from the contract header, as follows?

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

contract HelloWorld is Destroyable { ... }
2 Likes

Nice point @jon_m :+1: Later I saw that at the next videos. Besides the constructor would move to inherited contract, Ownable.sol with internal, right?

1 Like

Yes, the constructor should also move to Ownable.sol as it is part of our “root” functionality which establishes the contract owner on deployment.
You could mark the constructor with internal visibility, but then you wouldn’t be able to deploy Ownable.sol as a stand-alone contract, only as an inherited contract (i.e. by deploying either Destroyable or HelloWorld). This wouldn’t be a problem in our example, because we only want to deploy HelloWorld (together with its inherited functionality), so you could use either internal or public visibility. The issue surrounding constructor visibility is discussed in the following link:


However, we are using Solidity v5, and it is important to note what the last person says in this discussion thread: since Solidity v7 visibility is no longer stated for constructors. Without going into the details, and how this ties in with public v internal visibility, I think for now it’s probably just easier to keep things simple and mark your constructor with public visibility. Not that I don’t want to discourage you from researching more about this yourself if you’re interested to go deeper! :muscle: However, it involves the concept of abstract contracts, which are out of the scope of this 101 course.

When I mentioned internal visibility in my previous post, I was referring to the state variable owner (not to the constructor). If you mark it with public, then a getter will automatically be created which can be called from outside to view its value. However, if you want to avoid this, it would be better (in terms of “tighter” code) to use internal visibility, rather than just not state the visibility (as you have currently done).

I hope that makes things clearer :slight_smile:

1 Like

Ah I see, thank you for valuable information.

1 Like

Since owner was already set in Ownable I just made Destroyable inherit from that and HelloWorld inherits from Destroyable. Reduces the code.

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

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

Top of HellowWorld

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

contract HelloWorld is Destroyable
{
1 Like

Created Destroyable.sol to contain:

import “./Ownable.sol”;
pragma solidity 0.5.12;
contract Destroyable is Ownable{
function destroyContract() public onlyOwner {
selfdestruct(msg.sender);
}
}

1 Like

pragma solidity 0.5.12;
import ‘./Destroyable.sol’;

contract HelloWorld is Destroyable …

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

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

contract Destroyable is Ownable{
    function eraseContract () public onlyOwner{
        selfdestruct(owner);
    }
}
2 Likes

ok, I did’t get that the owner needs to be payable address.

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

Hi @explorergeek,

Yes, that works, as long as you make an additional change to Ownable. What modification did you have to make there, so that you can use owner as the argument for selfdestruct() instead of msg.sender?