Inheritance Assignment

Hey @M.K

owner should be payable if you want to use it as argument of selfdestruct().

Cheers,
Dani

1 Like
import "./Ownable.sol";

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

Hey Daniele, should be payable be written as below ?

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

Or how should i write the code ?
Cheers,

Hey @M.K

Should be selfdestruct (payable(owner));

Have a nice Sunday,
Dani

1 Like

When I created the contract and added the following code, I received an error that owner must be payable. I think this is because if the contract calls selfdestruct it returns funds to the owners address.

pragma solidity 0.7.5;

import './Ownable.sol';

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

I thought about changing Ownable.sol, but decided I didn’t want every contract that inherited Ownable to consider it payable.

I resolved the the issue within destroyable.sol as follows:

pragma solidity 0.7.5;

import './Ownable.sol';

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

Question:

I’ve looked at the assignment solution code -
address payable receiver = msg.sender;

Isn’t this functionally identical to simply ‘address payable owner’ given that only the owner should be able to use this function?

Unless I’m missing something the way I’ve done it is simply setting it as an absolute rather than determined by retrieving the sending address (which must be owner),

I thought about there perhaps being an issue with having multiple derived contracts inheriting Ownable, each having a different owner. I cannot work out whether or not this is a problem and if it is functionally how that problem works.

Hey @Shadesvox

Isn’t this functionally identical to simply ‘address payable owner’ given that only the owner should be able to use this function?

Yes is the same thing.
I would use msg.sender to avoid a variable declaration that costs gas and is not useful here.

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

Cheers,
Dani

Does this work? If the owner isn’t specifically declared as payable in the Ownable.sol contract I think this runs into the same problem.

In all the solutions I’ve seen so far there’s been some way to specify the sender/owner as payable (since selfdestruct returns funds to msg.sender)

Ok, so I thought more about this and msg.sender is payable since it’s an address. Is the problem that owner is an object rather than an address? I’m proper confused here.

Why is this the answer in the solution code?:

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

Hi @Shadesvox

sefldestruct requires a payable address as argument, therefore the function you’ve posted works.
You can test it by creating a simple contract on Remix.

Cheers,
Dani

Ok so I simply just used a similar function that was given as an example in the blog we had to read. However when i tried to say selfdestruct(owner) it was throwing an error so i replaced owner with msg.sender. I should probably fix that bug so it works for owner, maybe create a modifier or something.

I also could have put this function in its own separate file and then in the bank contarct inherit from both the ownable contract and the destroy contract using notation like

function Bank is Ownable, Destroyable {......

but i i thought why not just leave it in the own able file to save creating an extra file. It seems just fine here. If i should put it in its own file someone let me know and i will do so if its better practice. Heres my solution code anyway. I added in a bool so the function returns true if executed

  contract Ownable
{
  //make address public so we have access amount all levels of inheritance
  address owner;

modifier onlyOwner
{
    require(msg.sender == owner);
    
    
    _;//means run the function
}

//create a constructor for user input
constructor()
{
    owner = msg.sender;
}

//here we can add a destroy contarct function to kill al
//inheriting contracts from this base contratc in the case of
//some bug or internal issuof
function close() public onlyOwner returns(bool)
{
    //when the function is called we want to 
    //destroy the owners address
    selfdestruct(msg.sender);
    
    return true;
}

}

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

contract Destroyable {
    
    address owner;
    
    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }
    
    constructor() {
        owner = msg.sender;
    }
    
    function close() public onlyOwner { 
        selfdestruct(owner);
    }
    
}
1 Like

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

contract Destroyable is Ownable {

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

1 Like

HI Daniele , what is the below code found in transfer function about ?

govermentInstance.addTransaction(msg.sender, recipient, amount);

where did governmentInstance come from ?
where did .addTransaction come from ?

Please advise

I copied the solution below for your reference

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

contract Bank is Ownable, Destroyable {
    
    mapping(address => uint) balance;
    
    event depositDone(uint amount, address indexed depositedTo);
    
    function deposit() public payable returns (uint)  {
        balance[msg.sender] += msg.value;
        emit depositDone(msg.value, msg.sender);
        return balance[msg.sender];
    }
    
    function withdraw(uint amount) public onlyOwner returns (uint){
        require(balance[msg.sender] >= amount);
        msg.sender.transfer(amount);
        return balance[msg.sender];
    }
    
    function getBalance() public view returns (uint){
        return balance[msg.sender];
    }
    
    function transfer(address recipient, uint amount) public {
        require(balance[msg.sender] >= amount, "Balance not sufficient");
        require(msg.sender != recipient, "Don't transfer money to yourself");
        
        uint previousSenderBalance = balance[msg.sender];
        
        _transfer(msg.sender, recipient, amount);
        
        govermentInstance.addTransaction(msg.sender, recipient, amount);
        
        assert(balance[msg.sender] == previousSenderBalance - amount);
    }
    
    function _transfer(address from, address to, uint amount) private {
        balance[from] -= amount;
        balance[to] += amount;
    }
    
}

Those 2 comes from the interface for the goverment contract, you should be able to learn how to use interfaces from other contracts in further lessons.

Carlos Z

1 Like

contract Destroyable{

address payable owner;

constructor() {
    owner = msg.sender;
}


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


function selfDestruction() public onlyOwner {
    selfdestruct(owner);                         //owner will receive all the remaining funds from the contract before selfdestruction
}

}

1 Like

Hello. Why does Bank inherit from Ownable, and not the other way around? Does it matter which inherits from which?

1 Like

It does matter, which should be the parent contract? contracts like ownable just have some functions that the bank contract can inherit, so basically depends on which contract should be parent and which are childs (like ownable).

Carlos Z

import "./owner.sol";

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

@M.K, If you want you could just create your own function within your bank contract to create a transaction log but i think the reason it was done like this is just to show what can be done with solidiity like here we are getting shown to external contracts and how they can be used in a variety of suituations.

1 Like

Here are my codes for the Destroyable contract:

pragma solidity 0.8.3;

contract Destroyable {
    
    address owner;
    
    event destroyed(address holder, string message);
    
    constructor(){
        owner = msg.sender;
    }
    
    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }
    
    function close() public onlyOwner {
        emit destroyed(owner, "Contract destroyed!");
        selfdestruct(payable(owner));
        
    }
    
    
}

I tried, but without success, finding a way to verify the contract has been destroyed after the close function is executed, so I just make the function to emit an event right before the contract is destroyed to log the action. Don’t think it’s an optimal solution. Any suggestions?

Thanks!

2 Likes