Inheritance Assignment

I understand that Ownable is needed to be inherited in Bank contract but I think it is not necessary to write:

contract Bank is Ownable, Destroyable {

And it can be just written as below:

contract Bank is Destroyable {

Because if Bank inherits from Destroyable and Destroyable inherits from Ownable, it seems that Bank has also access to public variables defined in Ownable contract due to “multi-level inheritance”. Am I right?

1 Like

Are you saying you don’t necessarily need to assign address payable receiver to msg.sender? You can just streamline it as…

function destruction() public onlyOwner {
selfdestruct(msg.sender);

Also after I tested the functions… deposited money from several different accounts into the bank…, was the owner(msg.sender) suppossed to receive all the funds from the various deposits I made from other accounts after I hit destroy? Or does the account balance set to zero? I thought the owner account would be receiving the total of all the deposits made into the account after the destruct was performed but my balance shows zero after destructing. Thanks again for the clarification.

Indeed, I have made this code to show that Bank can inherit Ownable through Destroyable.

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

// usual owner routines
contract Ownable {
    
    address public owner;
    
    constructor(){
       owner = msg.sender; 
    }
    
    modifier onlyOwner() {
        require(msg.sender == owner,"onlyOwner allowed");
        _;    
    }
}

// destroy contract, must access Ownable to use onlyOwner
contract Destroyable is Ownable{
    function closeContract() public onlyOwner{
        selfdestruct(msg.sender);
    }
}

// bank contract, inherit Ownable through Destroyable
contract Bank is Destroyable {
    
    function deposit() public payable{}
    
    function getContractBalance() public onlyOwner view returns(uint256){
        return address(this).balance;
    }
    
}

Carlos Z

OWNABLE

pragma solidity 0.8.6;

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

DESTROYABLE

pragma solidity 0.8.6;

import "./ownable.sol";

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

BANK

pragma solidity 0.8.6;
import "./destroyable.sol";

contract Bank is Destroyable{
//only change in bank
function withdraw(uint amount) public returns (uint){
        require(balance[msg.sender] >= amount);
        balance[msg.sender] -= amount;
//here (for solidity version 0.8.6)
        payable(msg.sender).transfer(amount);

        return balance[msg.sender];
    }
}
1 Like

contract Ownable{

address owner;

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

constructor () {
    owner=msg.sender;
}

}

import “./ownable.sol”;

contract Destroyable is Ownable{

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

}

pragma solidity 0.7.5;

import “./destroyable.sol”;

contract Bank is Destroyable {

}

1 Like

// In hello world

import “./Destroyable.sol”;

contract Bank is Ownable, Destroyable {

// In Destroyable

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 Filip! As I look at the solution I can´t recognize this line:

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

And when I try to implement it I get an error message. Why is that? error message

1 Like

Hey @PoeAslan, hope you are ok.

That one comes from the government contract that you made before the bank contract. If you are not using it anymore, you can remove that code line.

Carlos Z

Hi, code of two files Ownable, Destroyable are below. Kindly please check .

pragma solidity >=0.7.0 <0.9.0;

/*

  • @title Owner

  • @dev Set & change owner
    */
    contract Owner {

    address private owner;

    // event for EVM logging
    event OwnerSet(address indexed oldOwner, address indexed newOwner);

    // modifier to check if caller is owner
    modifier isOwner() {
    require(msg.sender == owner, “Caller is not owner”);
    _;
    }

    /*

    • @dev Set contract deployer as owner
      */
      constructor() {
      owner = msg.sender; // ‘msg.sender’ is sender of current call, contract deployer for a constructor
      emit OwnerSet(address(0), owner);
      }

    /*

    • @dev Change owner
    • @param newOwner address of new owner
      */
      function changeOwner(address newOwner) public isOwner {
      emit OwnerSet(owner, newOwner);
      owner = newOwner;
      }

    /*

    • @dev Return owner address
    • @return address of owner
      /
      function getOwner() external view returns (address) {
      return owner;
      }
      }
      /
      ********************************************************************************************************/
      pragma solidity >=0.7.0 <0.9.0;

contract Destroyable {

address payable private owner;
uint256 number;

constructor() {
owner = msg.sender;
}

function store(uint256 num) public {
number = num;
}

function retrieve() public view returns (uint256){
return number;
}

function close() public {
selfdestruct(owner);
}

}
/********************************************************************************************************/
pragma solidity 0.7.5;
import “./2_Owner.sol”;
import “./4_Destroyable.sol”;

contract Bank is Owner, Destroyable {

}
/********************************************************************************************************/

Thank you in advance,
Andrei

1 Like

Ownable.sol

pragma solidity 0.7.5;
contract Ownable{
    address payable internal owner;
    constructor(){
        owner = msg.sender;
    }
    modifier ownerOnly{
        require(msg.sender == owner, "you are not owner");
        _;
    }
} 

Destroyable.sol

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

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

Bank.sol

pragma solidity 0.7.5;
import "./Destroyable.sol";
contract Bank is Destroyable{
    
    mapping(address=> uint) public balance;
    uint public bankBalance = 0;
    
    /* --------- */
    function Deposit() public payable {
        balance[msg.sender]+=msg.value;
        bankBalance+=msg.value;
    }
    
    function Withdraw(uint amount) public {
        require(balance[msg.sender]>=amount, "insufficient balance");
        msg.sender.transfer(amount);
        balance[msg.sender]-=amount;
        bankBalance-=amount;
    }
    
    function getBalance() public view returns(uint) {
        return balance[msg.sender];
    }
    
    function Destruct() public ownerOnly{
        msg.sender.transfer(bankBalance);
        bankBalance = 0;
        close();
    }
2 Likes
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;
    }
    
}

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

contract Destroyable is Ownable {

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



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

contract ownable {

address owner;

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

constructor() {
     owner = msg.sender;
 }

}

import “./ownable.sol”;

contract destroyable is ownable {

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

}

pragma solidity 0.7.5;

import “./ownable.sol”;

import “./destroyable.sol”;

contract etherBank1 is ownable, destroyable {

Worked fine!

1 Like
contract Ownable {
    address public owner;
    
    constructor(){
        owner = msg.sender;
    }
    
    modifier onlyOwner{
        require(msg.sender == owner);
        _;
    }
}
import "./Ownable.sol";

contract Destroyable is Ownable {
    function close() public onlyOwner{
    address payable bagPuller = msg.sender;
    selfdestruct(bagPuller);
    //selfdestruct(msg.sender); //can replace this line with the 2 previous
    }
}
pragma solidity 0.7.5;

import "./Destroyable.sol";
//import "./Ownable.sol"; //Not required now since we inherit via Destroyable
contract Bank is Destroyable{
    //code of Bank contract not modified
    }

So my question is:
I wanted to give back the ETH to each address using the balance mapping. Since I can not know in principle all the addresses that made a deposit, what should I do?
Does indexing helps?
Do I use events like DepositDone?
It is said I can create a new contract upon calling selfdestruct. Do I transfer the funds there keeping the old ballance mapping?

Got my self the same questions. Thank you and @jon_m

2 Likes

Thank you. The pleasure is all mine!

1 Like

Ownable.sol

pragma solidity 0.7.5;

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

Destroyable.sol

pragma solidity 0.7.5;

import "./ownable.sol";

contract Destroyable is Ownable{
    event isDestroyed(bool status);
    function killContract() onlyOwner public{
        emit isDestroyed(true);
        selfdestruct(owner);
        //ALL remaining ether in the contract gets automatically transfered to the owners address (detirmend by the adress set in selfdestruct(_HERE_))
        //on self destruct. (the token mappings however are lost.)
    }
}

in bank.sol I only added import “./destroyable” as for the bank contract adding it would just be redundant since it already inherits it in destroyable.


import "./destroyable.sol";

contract transferAssignment is Destroyable{
1 Like

ownable.sol :
pragma solidity 0.7.5;
//SPDX-License-Identifier: UNLICENSED

contract ownable {

address payable public owner;

constructor() {
    owner = msg.sender;
}

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

}

destroyable.sol:

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

import “./ownable.sol”;

contract destroyable is ownable {

function destroy() public onlyOwner { 
   selfdestruct(owner); 
}

}

bank.sol:
pragma solidity 0.7.5;
//SPDX-License-Identifier: UNLICENSED

import “./ownable.sol”;
import “./destroyable.sol”;

contract Bank is ownable, destroyable {


etc…

1 Like

Created Destroyable.sol which inherits Ownable

pragma solidity >0.6.0;

import "./Ownable.sol";

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

changed Bank.sol to inherit only Destroyable because Destroyable inherits Ownable

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

contract Bank is Destroyable {
1 Like

Hi, here is my solution

A - First contract Destroyable, please note that I mentioned destruct function as internal. It will be later inherited by bank contract.

//SPDX-License-Identifier: MIT
//Destroyable - A contract to provide self-destruct functionality.

pragma solidity 0.7.6;

contract Destroyable {
    address payable private owner;

    constructor() {
        owner = msg.sender;
    }

    function destruct() internal {
        selfdestruct(owner);
    }
}

B - Ownable contract

//SPDX-License-Identifier: MIT
//Ownable - A contract to check ownership.

pragma solidity 0.7.6;

contract Ownable {
    address owner;

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

    constructor() {
        owner = msg.sender;
    }
}

C - Main Bank contract, here I inherited Ownable and Destroyable both. I called Destroyable.destruct(); function within kill function. Only owner can call kill function and contract should not have any balance.

//SPDX-License-Identifier: MIT
//Bank - A sample contract.

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

pragma solidity 0.7.6;

contract Bank is Destroyable, Ownable {
// rest of code is same as previous examples
//
//
function kill() public onlyOwner {
        require(
            balance[msg.sender] == 0,
            "Contract still   has balance, please empty."
        );
        Destroyable.destruct();
    }
}

Looking forward for suggestions.
Israr

1 Like

pragma solidity 0.7.5

Import “./Ownable.sol”;

contract Destroyable is Ownable {

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

1 Like