Inheritance Assignment

//Does it matter which contract you use as the base or derived contract? It does not seem so since both share the same functionality. I used “destroyable is Destroyer” and it compiled and gave me a button to close the contract. If I close the contract won’t it be the contract that I have open that will be destroyed? I am a litter scared to push the button. Will the contract just disappear.
Also I am not understanding why when I close the contract using owner I get an error but when I use msg.sender it compiles. Why even create the owner in that case?
Here is the code for the destroyable which is just a copy one of our old contracts.

pragma solidity 0.7.5;

import "./ToDestroy.sol";

contract destroyable is Destroyer{

    mapping(uint => User)users2;

    struct User{
        uint id;
        uint balance;
    }
    
    User[]users1;
    
    function addUser(uint _id, uint _balance) public {
        User memory newUser = User(_id,_balance);
        users1.push(newUser);
        
    }

    function updateBalance(uint _id, uint _addBalance) public {
    
         users1[_id].balance =  users1[_id].balance + _addBalance;
    }

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

// And here is the ToDestroy contract with the Destroyer contract.


pragma solidity 0.7.5;

contract Destroyer{
    
    address owner;
    
   modifier onlyOwner{
    require (msg.sender == owner,"You are not the owner of contract and permission is denied to destroy contract");
    _;
   }
   
    constructor(){
        owner = msg.sender;
    }
    
    function close() public onlyOwner{
        selfdestruct(msg.sender);
    }
    
}

Here is my solution to the inheritance assignment.

pragma solidity 0.7.5;

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

import "./Ownable.sol";

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

@thecil … thanks so much - i feel pretty stupid for not seeing that !

lol, dont feel stupid, you have no idea how many times this will happen, is more than common to be honest, yesterday i was working on my personal project and was trying to figure it out why my contract was not working when checking the code was completely good, but i forgot to update the changes on the interface :rofl:

//I had to use msg.sender in the close function because using owner did not work. Don’t understand why when we set msg.sender = owner. And why did we have to a constructor for msg.sender = owner and not just add state variable owner and set equal to msg.sender?

Destroyer adds button and get green check that it ran but dont see where in the code that it actually did something,

pragma solidity 0.7.5;

import "./ToDestroy.sol";

contract destroyable is destroyer{

    mapping(uint => User)users2;

    struct User{
        uint id;
        uint balance;
    }
    
    User[]users1;
    
    function addUser(uint _id, uint _balance) public {
        User memory newUser = User(_id,_balance);
        users1.push(newUser);
        
    }

    function updateBalance(uint _id, uint _addBalance) public {
    
         users1[_id].balance =  users1[_id].balance + _addBalance;
    }

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

// Destroyer Code

pragma solidity 0.7.5;

contract destroyer{
    
    address owner;
    
   modifier onlyOwner{
    require (msg.sender == owner,"You are not the owner of contract and permission is denied to destroy contract");
    _;
   }
   
    constructor(){
        owner = msg.sender;
    }
    
    function close() public onlyOwner{
        selfdestruct(msg.sender);
    }
    
}

pragma solidity ^0.7.5;

contract Ownable {

address payable public owner;

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

constructor() {
    owner = msg.sender;
}

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

}

1 Like
import"./Ownable1.sol";
import"./Destroyable1.sol";
pragma solidity 0.7.5;

contract HelloWorld is Ownable, Destroyable{
``` //etc

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

contract Ownable{
    
    address owner;
    
    modifier onlyOwner {
       (msg.sender == owner);
       _; //Run function
   }

   modifier cost(uint price){
       require(msg.value >= price);
       _; //Run function
   }
   constructor(){
       owner = msg.sender;
   }
    
}

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


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

import "./ownable.sol";

contract Destroyable is Ownable{
    
    function destroy() internal onlyOwner {
        selfdestruct(owner);
    }
    
}
1 Like

contract Destroyable{
address public owner;

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

}

1 Like

Ok, so I found the solution after some errors, lol.

Selfdestruct contract:

pragma solidity 0.7.5;

import "./Ownable.sol";

contract Selfdestruct is Ownable{
    
    function closeContract() public onlyOwner { //onlyOwner access, public
        address payable receiver = msg.sender;
        selfdestruct(receiver); //destroys contract
    }
    
}

We need to make sure that the **receiver address is from the owner!** Therefore **onlyOwner modifier is crucial.**

Update in Etherbank contract:

pragma solidity 0.7.5;

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

contract EtherBank is Ownable, Selfdestruct{

mapping (address => uint) balance; //takes in a key, here an adress, and returns a value, here uint


//events can be used to log history of contract use! Very interesting and important :) 
event depositDone(uint amount, address depositedTo); //creates event takes in parameters we want in the log
event wasTransfered(address indexed sender, uint amount, address transactionrecipient); //if a parameter is indexed we can search for it on the blockchain! we can use infinite amount of parameters but a max of 3 parameters can be indexed per event!



modifier costs(uint price){ //checks if sent value can cover costs/fees
    require(msg.value >= price);
    _;
}

modifier notSenderAddress(address recipient){
    require(msg.sender != recipient, "Do not send money to yourself!"); //prevents sender to send money to him/herself --> same address
    _; 
}

modifier enoughBalance(uint amount){
     require(balance[msg.sender] >= amount, "Insufficient Funds!"); //if condition is not met function will abort and throw error. Here: if balance of sender is not higher or equal to amount to send
    _;
}


function deposit() public payable returns (uint){ //takes in uint for ammount to add to adress, returns a uint with the new balance
    //since function is payable, deposits will be stored in the wallet of the contract on the blockchain
    //the balance mapping is only to keep track of balances inside the code of the contract, so therefore it can also be deleting since payable modifier will store everything on blockchain now
    balance[msg.sender] += msg.value; //accessing mapping balance with address of sender and adds user input value
    emit depositDone(msg.value, msg.sender); //emit casts event to log!
    return balance[msg.sender]; //returns balance of sender address
    
}
 function withdraw(uint amount) public onlyOwner enoughBalance(amount) {
    //store previousSenderBalance
    uint previousSenderBalance = balance[msg.sender];
    //msg.sender is exactly the same as address payable toSend = PUTADDRESSHERE, so you can define a payable adress like this. msg.sender already is a payable address!!
    msg.sender.transfer(amount);
    //if transfer fails for some reason contract throws error and reverts the transaction
    balance[msg.sender] -= amount;
    
    assert(balance[msg.sender] == previousSenderBalance - amount);
}

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

function transfer(address recipient, uint amount) public notSenderAddress(recipient) enoughBalance(amount){ //transfers uint amount to address of recipient
    //check of balance from sender is in modifer enoughBalance now!
   
    
    uint previousSenderBalance = balance[msg.sender];
    
    _transfer(msg.sender, recipient, amount); //decreases balance of msg.sender wallet & increases balance of recipient wallet --> see private _transfer function
    
    emit wasTransfered(msg.sender, amount, recipient);

    assert(balance[msg.sender] == previousSenderBalance - amount);

    //event logs and further checks missing
    
    //assert, check for invariant
}

function _transfer(address sender, address receiver, uint amount) private { //private transfer function! implemented in public transfer function see above
    
    balance[sender] -= amount; //decreases balance of sender address
    balance[receiver] += amount; //increases balance of receiver address
    
}

}

1 Like
pragma solidity 0.8.1;

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

address owner;

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

  constructor(){
      owner = msg.sender;
  }

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

}
1 Like
pragma solidity 0.7.5;

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

contract Destroyable{
    
    address public owner;

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

1 Like

Hi Janja,

Yes, if you want to have the option to destroy the contract in the event of a serious bug or hack etc.

You can do it this way, but there is no need to change your original code:

By inheriting Destroyable, Bank will also inherit Ownable via Destroyable (because Destroyable already inherits Ownable). This is what is known as multi-level inheritance. The onlyOwner modifier defined in Ownable will be available to restrict access to functions in both Destroyable and Bank.

1 Like

contract Destroyable {

address public owner;

constructor() {
    owner = msg.sender;
}

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

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

}

1 Like

Here is my code:

contract Destroyable {
address public owner;
modifier onlyOwner {
require(msg.sender == owner);
_;

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

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

1 Like
pragma solidity 0.7.5;

import "./Ownable.sol";

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

I hope this is right:

pragma solidity 0.7.5;

import “./Ownable.sol”;

contract Destroyable is Ownable {

function close() public onlyOwner { 
    selfdestruct(Owner);  
}

}

1 Like

i have copyed and paseted the selfdestruct code, but when i deploy it, and do the close function the contract selfdstructs. So when i send funds to the contract, those funds are lost right? meaning i cant withdraw funds?

pragma solidity 0.7.4;

import './ownable.sol';

contract bank is ownable{
    
    mapping(address => uint) balance;
    
    event depositdone(uint amount,address indexed depositedto);
    
    function createbalance(address to,uint amount) public onlyowner returns(uint){
        balance[to] += amount;
        return balance[to];
    }
    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 returns(uint){
        require(amount<=balance[msg.sender],'not enoughbalance');
        msg.sender.transfer(amount);
        balance[msg.sender] -= amount;
        return balance[msg.sender];
    }
    function viewbalance() public view returns (uint){
        return balance[msg.sender];
    }
    
    function transfer(address reciver, uint amount) public{
       require(balance[msg.sender] >= amount, 'not enough balance');
       //require(msg.sender!= reciver, 'dont send funds to yourself');
        _sendbalance(msg.sender, reciver, amount);
        
    }
    function _sendbalance(address from, address to, uint amount) private{
        balance[from] -= amount;
        balance[to]+= amount;
    }
    function close() public onlyowner { //onlyOwner is custom modifier
    selfdestruct(msg.sender); 
}
2 Likes