Inheritance Assignment

Hi @bencoin

This works as long as owner is payable :slight_smile:

Happy learning,
Dani

import “./Owneable.sol”;

contract Destroyable is Owneable {
function destroy() public onlyOwner {
selfdestruct(msg.sender);
}
}

And in HandledContract

contract HandledContract is Owneable , Destroyable {

1 Like

//In Bank Contract```
pragma solidity 0.8.2;
import “.tiger.sol”; //ownable Contract
import “vaccine.sol” //Destroyable Contract
contract Bank is Ownable{
mapping (address => uint) balance;
event depositedDone(uint amount, address indexed despositedTo);
}

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

In the destruction.sol file:

import "./Ownable.sol";

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

in the helloworld.sol file:

pragma solidity 0.8.2;

import "./Ownable.sol";
import "./destruction.sol";

contract Bank is Ownable, Destroyable
1 Like

//solich.sol

pragma solidity 0.8.2;
// SPDX-License-Identifier: UNLICENSED


import "./ownable.sol";
import "./destroyable.sol";
contract solich is Ownable, Destroyable{

mapping(address => uint)balance;   

event depositDone(uint amount, address indexed depositedTo);
event widthrawDone(uint amout, address indexed widthrawTo);

function deposit() public payable returns (uint){
    balance[msg.sender] += msg.value;
    emit depositDone(msg.value, msg.sender);
    return balance[msg.sender];
}

function widthraw(uint _amount) public returns (uint){
    //requires always come first!
    require(_amount>0);
    require(balance[msg.sender] >=_amount, "you don't have that much ETH");
    uint targetBalance;
    targetBalance = balance[msg.sender] - _amount;
    payable(msg.sender).transfer(_amount);
    balance[msg.sender] -= _amount;
    assert(targetBalance == balance[msg.sender]);
    emit widthrawDone(_amount, msg.sender);
    return balance[msg.sender];
}



function removeBalance(uint _amount, address _address) public onlyOwner {

    uint previousBalance = balance[_address];
    previousBalance -= _amount;
    require(balance[_address]>=_amount, "you can't have less then 0 tokens");
    balance[_address] -= _amount;
    assert(balance[_address] == previousBalance);
    
}

function getBalance() public view returns (uint){
    return balance[msg.sender];
}



function transfer(uint _amount, address _recipient)public{
    
    uint previousBalance;
    require(_amount>0);
    require(balance[msg.sender] >= _amount, "you don't have enough tokens");
    require(msg.sender != _recipient, "don't send tokens to yourself");
    previousBalance = balance[msg.sender] - _amount;
    _transfer(msg.sender, _recipient, _amount);
    
 
    assert(previousBalance == balance[msg.sender]);
}

function _transfer(address _from, address _to, uint _amount) private{
    
    balance[_from] -= _amount;
    balance[_to] += _amount;
}
}

//ownable.sol

// SPDX-License-Identifier: MIT

pragma solidity 0.8.2;

contract Ownable{
    address owner;
    constructor(){
    owner = payable(msg.sender);
}
    modifier onlyOwner {
   require(msg.sender == owner);
   _;//run the function
}
}

// destryoable.sol

// SPDX-License-Identifier: MIT

pragma solidity 0.8.2;
import "./ownable.sol";
contract Destroyable is Ownable{
    
    function close() public onlyOwner{
    selfdestruct(payable(owner));
}
}
1 Like
pragma solidity 0.7.5;

import "./Ownable.sol";

contract Destroyable is Ownable {
    
    function destroyIt() public onlyOwner {
        selfdestruct(msg.sender);
    }
}
2 Likes
pragma solidity 0.7.5;

import"./Ownable.sol";

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

Helloo @dan-i ,

Ok I have a question, if destroyable.sol inherits from ownable.sol why does Filip in his solutions assigns a new variable to msg.sender ?
I understood that that’s done in ownable.sol , or not?

Thank you :blush:

1 Like

I had to change the “address owner” variable in the Ownable contract to:

address payable public owner;

Without this change I got an error requesting that I change the argument of selfdestruct() (in this case “owner”) from address to address payable. I find this a bit odd because owner has been set to msg.sender and msg.sender is a payable address. Is this because owner only gets set to msg.sender once the contract is deployed and thus at the time of defining the selfdestruct() function owner is NOT yet equal to msg.sender?

Anyway, here is my answer:

import “./Ownable.sol”;

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

Ps. I’ve just had a look at the answer, which is different to mine. Filip writes the function as:

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

Is my way still correct meaning that there are more than one ways to write the selfdestruct() function, or is Filip’s way correct/better? If so, why?

Test self-destruct function :

// SPDX-License-Identifier: MIT
pragma solidity ^0.7.5;
import "./ownable.sol";

contract Destroyable is Ownable {
    
 address payable private accountOwner;
 uint256 number;
 
 constructor() {
  accountOwner = msg.sender;
 }
 
 function store(uint256 num) public {
  number = num;
 }
 
 function retrieve() public view returns (uint256){
  return number;
 }
 
 function close() public onlyOwner { 
  selfdestruct(accountOwner); 
 }
}
1 Like

Hey @Karla

I assume this is the piece of code you are referring to:

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

The function selfdestruct() requires one parameter of type address payable that will receive all the remaining Ether in the contract.
Once clarified that you can really use the variable you prefer.

You could use owner for example:

selfdestruct(payable(owner));

You could use msg.sender:

selfdestruct(payable(msg.sender));

You could create a variable and bind msg.sender to it:

address payable receiver = msg.sender;
    selfdestruct(receiver);

It really does not matter as long as you provide a payable address.

Happy coding,
Dani

1 Like

Hi @Emmerich

Please read this FAQ that explains how to post readable code in the forum: FAQ - How to post code in the forum

I find this a bit odd because owner has been set to msg.sender and msg.sender is a payable address.

If you are using Soldity 0.8 or higher keep in mind that msg.sender is not payable anymore.

If you are using Solidity < 0.8 msg.sender is payable but if you bind it to a non-payable address it also becomes not payable.

address a = msg.sender; // not payable

address payable a = msg.sender // payable

Cheers,
Dani

Hi @dani,

Ok thank you and yes you assumed right! Just to clarify and make sure I understand, when destroyable inherits from ownable

contract Ownable {
    address internal owner;
    
    modifier onlyOwner {
        require(msg.sender == owner);
        _; //run the function
    }
    
    constructor(){
        owner = msg.sender;
    }
}

would I have to set the constructor to address payable owner = msg.sender;
or do I have to declare it in the destroy() function?

pragma solidity 0.7.5;

contract Ownable{
    address payable internal owner;
    
    modifier onlyOwner{
        require(msg.sender == owner);
        _;
    }  
    constructor(){
        owner=msg.sender;
    }
}
pragma solidity 0.7.5;

import "Ownable.sol";
contract Destroyable is Ownable {
    function closeContract() public onlyOwner {
        selfdestruct(owner);
    }
}
1 Like

Perfect, thanks for the tip on formatting! And also for taking the time to answer :slight_smile:

1 Like

Hey @Karla

There is not a rule, you can proceed the way you like the most.
For example I would not declare owner as payable, I would just cast msg.sender passed to selfdestruct.

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

Because the function uses a modifier onlyowner, you know that msg.sender == owner.
So I would just cast msg.sender to payable.

Cheers,
Dani

1 Like

Ownable contract:

pragma solidity 0.7.5;

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

Destroayble contract:

pragma solidity 0.7.5;

import "./ownable.sol";

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

Contract inheriting from Destroyable:

pragma solidity 0.7.5;

import "./ownable.sol";
import "./destroyable.sol";

contract Test is Ownable, Destroyable {

And maybe I don’t even have to put Ownable into inheriting contract, because it already inherits Ownable from Destroyable?

1 Like

Ownable contract:

pragma solidity 0.7.5;

contract Ownable {  
    address public owner;
    
    modifier onlyOwner {
        require(msg.sender == owner);
         _;  //means run the function
    }
    
    constructor(){
        owner = msg.sender;
    }
}

Destroyable contract, inheriting from Ownable contract:

pragma solidity 0.7.5;

import "/.Ownable.sol";

contract Destroyable is Ownable {
    function close() public onlyOwner { 
    selfdestruct(owner);  //this is stated as == msg.sender in Ownable contract
    }
}

then Bank contract inherits from Ownable and Destroyable:

pragma solidity 0.7.5;

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

contract Bank is Ownable, Destroyable {
//rest of code follows...

I have not looked at the solution video so maybe he addresses this, but a few of my questions right now are:

Since we have the constructor owner = msg.sender in the Ownable contract, should I have selfdestruct(owner) in the Destroyable contract or selfdestruct(msg.sender) like I see a few others putting here?

And, since Destroyable is inheriting from Ownable, and Bank is inheriting from Destroyable, do I also need to have it inheriting from Ownable? What is the best practice here?

after posting my answer, I looked up and saw that our posts are almost identical including the question about inheriting! :smile:

1 Like