Inheritance Assignment

Hi @biokillos,

Correct … Now 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:

Nice solution @chrisdbarnett :ok_hand:

Have a look at this post — it explains how and why you can steamline the inheritance code by having HelloWorld just inherit Destroyable. This may also help you to understand why the cleanest inheritance configuration involves Destroyable inheriting Ownable.

Yes, that’s one way to do it. An 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 Destroyable:

selfdestruct(address(uint160(owner)));

It could be done if:
(i) you pass msg.sender (instead of owner) to selfdestruct:
selfdestruct(msg.sender);
If msg.sender is used directly as a value like this (and not first assigned to a variable) then it is treated as a payable address by default in Solidity, and so it doesn’t need to be converted to a payable address like owner does;
and
(ii) the selfdestruct function wasn’t restricted to onlyOwner (which needs to be inherited from Ownable). However, I wouldn’t suggest giving everybody access to this functionality for obvious reasons!

Yes, that means that the contract has been successfully destroyed :+1:
:boom:

2 Likes

import"./Ownable.sol";

pragma solidity 0.5.12;

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

image
image

1 Like

Destroyable.sol:

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

contract Destroyable is Owned{
function close() public onlyOwner {
selfdestruct(address(uint160(owner)));
}
}

HelloWorld.sol:

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

contract HelloWorld is Owned, Destroyable{

1 Like

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

contract Destroyable is Ownable{

function closed() public onlyOwner { 

selfdestruct(msg.sender);
}

}

Helloworld

import “./Ownable.sol”;
import “./Destroyablable.sol”;

pragma solidity 0.5.12;

contract HelloWorld is Ownable, Destroyablable{

1 Like

Made new file Destroyable.sol

import “./ownable.sol”;
contract Destroyable is Ownable {
function close () public onlyOwner {
selfdestruct(msg.sender);
}
}

added to HelloWorld.sol
import “./Destroyable.sol”

and finally changed HelloWorld contract definition
contract HelloWorld is Ownable, Destroyable {

1 Like

// Hello world file

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

contract HelloWorld is Ownable, Destroyable{

struct Person {
  uint id;
  string name;
  uint age;
  uint height;
  bool senior;
}......

}

// Ownable file
pragma solidity 0.5.12;

contract Ownable{
address payable public owner;

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

}

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

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

}

1 Like

for the Destroyable contract:

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

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

}

for the helloWorld contract:

import "./Ownable.sol";
import "./Destroyable.sol";

pragma solidity 0.5.12;

contract HelloWorld is Ownable, Destroyable {
1 Like

Destroyable contract:

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

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

HelloWorld contract changes:

import './Destroyable.sol';

contract HelloWorld is Ownable, Destroyable {

Ownable contract modified woner address to payable:

address payable public owner;
1 Like

From Destroyable Contract

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

contract Destroyable is Ownable { // we  inherit the code needed from contract Ownable
    
function destroyContract() public onlyOwner { // The modifier we set up in contract Ownable 
    selfdestruct(msg.sender); // destruction can be achieved only by the owner 
}
    
}

From HelloPerson Contract

import "./Ownable.sol";
import "./Destroyable.sol"; // allow us to destroy HelloPerson contract
pragma solidity 0.5.12;

contract HelloPerson is Ownable, Destroyable {
1 Like

“Ownable.sol”:
pragma solidity 0.5.12;

contract Ownable {

// STATE VARIABLES

address public owner;

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

// FUNCTIONS

// Only runs once throughout the duration of the contract
constructor () public {
    owner = msg.sender;
}

}

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

contract Destroyable is Ownable{

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

}

“HelloWorld.sol”:
function closeContract () public onlyOwner {
deleteContract ();
}

1 Like

Here is the contract for the self destruct contract.

pragma solidity 0.5.12;

contract Destroyable {
     
     address payable private owner;
     
     constructor() public {
        owner = msg.sender;
     }
     
      function close() public { 
        selfdestruct(owner); 
     }
     
 }
1 Like

I was not sure how to get the our contract to point to the Destroyable child contract, so I just added another import command. Seems to compile fine.

import "./Ownable.sol";
import "./Destroyable.sol";

pragma solidity 0.5.12;

contract HeyYoungWorld is Ownable, Destroyable {
    
    struct Person {
        string name;
        uint age;
        uint height;
        bool senior;
        
    }
    
    event personCreated(string name, bool senior);
    event personDeleted(string name, bool senior, address deletedBy);
 
    uint public balance;
    
   
    /* modifier costs(uint cost){
        require(msg.value >= cost);
        _;
    }*/
    // Runs when at the time the contracy is created
   
    mapping(address => Person) private people;
    
    // An Array for saving addresses
    address[]private creators;  
    
    function createPerson(string memory name, uint age, uint height) public {
        
        require(age < 150, "Age needs to be less than 150.");
        // balance = balance + msg.value;
        
       //balance += msg.value;
       // check if payment is >= 1 ET
       // This creates a person 
        Person memory newPerson;
        newPerson.name = name;
        newPerson.age = age;
        newPerson.height = height;
         
         if(age >= 65){
            newPerson.senior = true;
         } 
         else{
            newPerson.senior = false;
         }
            insertPerson(newPerson);
            // Adds an entry into the Array
            creators.push(msg.sender);
            //people[msg.sender] == person 
            assert(
                keccak256(
                    abi.encodePacked(
                    people[msg.sender].name, 
                    people[msg.sender].age, 
                    people[msg.sender].height, 
                    people[msg.sender].senior
                    )
                )
                ==
                keccak256(
                    abi.encodePacked(
                    newPerson.name, 
                    newPerson.age, 
                    newPerson.height, 
                    newPerson.senior
                    )
                )
            );
            emit personCreated(newPerson.name, newPerson.senior);
    }        
    
    function insertPerson(Person memory newPerson) private{
        address creator = msg.sender; 
        people[creator] = newPerson;
        
    }
   
    function getPerson() public view returns(string memory name, uint age, uint height, bool senior){
      address creator = msg.sender;
      return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior);
    }
    
    function deletePerson(address creator) public onlyOwner {
        string memory name = people[creator].name;
        bool senior = people[creator].senior;
        
        delete people[creator];
        assert(people[creator].age == 0);
        emit personDeleted(name, senior, msg.sender);
    }
    
    function getCreator(uint index) public view onlyOwner returns(address) {
        return creators[index];
    }
}    
1 Like
  1. Create another file destroyable.sol
    2.Add function to destroy
    function close() public onlyOwner { selfdestruct(owner); }
  2. Create hierarchy inheritance
    Owner -> Destroyable -> Helloworld.
1 Like

HelloWorld.sol would have its contract extended like this:

contract HelloWorld is Ownable, Destroyable{ 

}

and the new Destroyable contract would contain the following code:

pragma solidity 0.5.12;

contract Destroy is Ownable {

    function closeContract() public onlyOwner {
        selfdestruct(msg.sender);
    }
}
1 Like

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

contract Destroyable is Ownable {

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

}

1 Like

Hi @keithra1948,

Well done for finding a way round not knowing how to get Destroyable to inherit Ownable. It does compile, but the problem is that the selfdestruct function is not restricted to onlyOwner, so anyone can call it. The other issue is that you also now have duplicated code in Ownable and Destroyable.

To solve these issues, and get Destroyable to inherit Ownable, you need to modify Destroyable as follows:

// Add at the top to import Ownable.sol
import "./Ownable.sol";

// Inherit contract Ownable
contract Destroyable is Ownable {...}

You can now remove the owner variable and the constructor from Destroyable, and only include them in Ownable, together with the onlyOwner modifier. You need to keep the owner variable payable, so that when it is inherited by Destroyable it can still be used in the selfdestruct function to transfer the remaining contract balance to the owner. However, you will have to now change its visibility from private to either internal or public, otherwise it won’t be available to Destroyable.

As Destroyable now inherits Ownable, you can also remove from HelloWorld the code which explicity inherits Ownable. This is because HelloWorld also inherits from Destroyable, and so now indirectly inherits Ownable via Destroyable.

Hi @Jun_0113,

If you pass owner as the argument to selfdestruct() instead of msg.sender, then you also need to either make an additional modification to contract Ownable, or add some additional code to contract Destroyable.

Do you know what this is, and why?

1 Like

Hi @ThisIsNotStefan,

Good… but don’t forget to import the files with the inherited contracts.

Also, …

… should be contract Destroyable, as contract Destroy doesn’t exist :wink:

1 Like