Inheritance Assignment

Hi @guillaume_M-D,

I’m glad those explanations and visual examples were helpful, and tied up some loose ends for you :slightly_smiling_face:

In terms of overall control and security it’s always best to restrict our variables to whatever is strictly necessary. For this reason I think Solidity makes it necessary for us to explicity declare a variable of type address as payable, rather than it being the default.

msg.sender is an obvious exception to this, as it is automatically payable without us having to declare it as such.

Does that answer your question?

1 Like

Yes, appreciate good sir.
All my best wishes, hope to meet again :slight_smile:

1 Like

Step 1: create Destroyable.sol

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

contract Destroyable is Ownable {

function closeContract() public onlyOwner {
selfdestruct(msg.sender);// msg.sender receives the funds
}
}

Step 2: import destroyable in HelloWorld.sol

import ‘./Destroyable.sol’;
contract HelloWorld is Destroyable{

Since Destroyable is already inheriting Ownable, by means of importing Destroyable, HelloWorld is also inheriting Ownable.

1 Like

Hi @Stefan_Guse

If
HelloWorld is Destroyable
and
Destroyable is Ownable
there is no circular inheritance.

Also with your method i don’t really see where you are adding more flexibility. As the destructor is define in your contructor when the contract will be deploy you ll not be able to change it. So you ll end up with the destructor behing the msg.sender
I guess you are using msg.sender as an example and the point is being able to change the destructor, so in this case why not defining the destructor as the owner of the contract in the constructor and just create a setter that only the owner can use to change the destructor

2 Likes

import “./Ownable.sol”;

pragma solidity ^0.6.0;

contract Destruction is Ownable {

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

}

1 Like
  1. Created new file Destroyable.sol, imported Ownable.sol and wrote the following:
import "./Ownable.sol";

pragma solidity 0.5.12;

contract Destroyable is Ownable {
    function destroy() public onlyOwner{
        selfdestruct(msg.sender);
    }
}
  1. Went back to the HelloWorld file and updated the following:
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 close() public onlyOwner{
        address payable owner = msg.sender;
        selfdestruct(owner);
    }
}
1 Like

Hi @gabba,
thanks for your feedback. Yes, choosing with the multi-level inheritance is probably the way to go, I guess the destruction of a contract should be left to its owner. As you correctly stated, msg.sender in the constructor was just an example, hence a bit more flexibility on deployment. An owner controlled setter would take this even one step further.

1 Like

function destory() public onlyOwner {

selfdestruct(msg.sender)
}

1 Like

Hi @Edward_Valencia,

Nice solution :ok_hand:

… 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.

Hi @jdbarrancs,

Your solution works :ok_hand:

However, I would probably use a different variable name for the local address payable you are creating. I would do this because we have already used owner to declare the non-payable owner’s address as a state variable in contract Ownable, and which is therefore also inherited by contract Destroyable. As I say, it doesn’t actually throw an error or affect successful deployment, but I think it could help with making the contract code more easy to understand.

Hi @Stefan_Guse,

@gabba

Just to add… (I’ve also been following this discussion about your particular assignment solution)…

Not necessarily. Your idea to add flexibility, so that someone other than the contract owner can be allowed to destroy the contract, is a good one. This could be a client for whom the contract has been written and deployed, for example.

I think the point here is that this flexibility is fine, as long as it’s only the owner address which is authorised to assign “destruction capability” to a different address. And this is where the setter (restricted to the owner) would be the best solution. And this can be done using the multi-level inheritance: Ownable inherited by Destroyable inherited by HelloWorld. For example:

/* I've tried to keep as much of your original code (variable names,
   syntax... etc.) as possible, so that it's easier to see how I've
   modified your solution, rather than just rebuilt the whole thing. */

// contract Destroyable

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

contract Destroyable is Ownable {
    address private destructor;
    
    function createDestructor(address _destructor) public onlyOwner {
        destructor = _destructor;
    }

    function destroy() public {
        require(msg.sender == destructor, 'You cannot do that');
        
        address payable beneficiary = address(uint160(destructor));
        selfdestruct(beneficiary);    
    }
}
// contract HelloWorld

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

contract HelloWorld is Destroyable {...}

By all means, let’s continue to discuss this, as I think you’ve raised some interesting points that are worth thinking about and exploring further :slightly_smiling_face:

1 Like

Hi @const9090,

Good solution for the actual function that destroys the contract :ok_hand:
… but could we maybe also see your whole contract Destroyable, to also see how you’ve implemented the inheritance? :wink:

1 Like
Import "./Ownable.sol";

pragma solidity 0.5.12;

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

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

contract Destroyable is Ownable{

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

}

1 Like

I have a conceptual question here for @filip or @jon_m . Since the selfdestruct function deletes the address, but that doesn’t necesarily destroy contract which could have other data, e.g. struct. So all we do when using that function is “taking away the ability for the contract to execute”, not purging the entire contract data? Is that correct, or am I confused?

1 Like

Thanks @jon_m that makes things a bit neater.

1 Like

Hi Li_Sun,

selfdestruct function is the high level representation of SELFDESTRUCT opcode. This one gives back some gas to the external account, that initiate the transaction, by deleting all contract’s data.
In ethereum, storing data cost gas.

1 Like

Destroyable.sol file:

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

contract Destroyable is Ownable{

    function selfDestruct() public onlyOwner { //onlyOwner is custom modifier
        address payable receiver = msg.sender;
        selfdestruct(receiver);  // `receiver` is the owners address but it was not payable so we had to turn it payable above
    }

}

HelloWorld.sol file:

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

contract HelloWorld is Ownable, Destroyable{
1 Like

Made a new contract that has the code:

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


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

Then in HelloWorld.sol file I included

import "./Destroyable.sol";

contract HelloWorld is Ownable, Destroyable {
1 Like