Inheritance Assignment

Thanks for the insight!

Re bank.sol, for (1) and (2) i just meant that the template/solution found at this github repo is not able to work due to (1) being missing. (2) works as intended but other users not being able to withdraw their deposits is a “bug”.

Realised what (3) was from the next lecture, indeed for external contracts, so that’s clarified now!

Cleared my doubts with this reply thanks again @Gry!

Enjoying this course a lot thank you Filip and Moralis team for putting it together!

2 Likes

It is basically mandatory that each contract (abstract or parent, library or what ever it is) to specify the version of solidity that is or has been used to program it. So basically its mandatory the pragma declaration for each contract.

I could say, no, its not an abstract contract since it does have some implementations by its own (like the modifier), while an abstract contract should have at least a declared function without any implementation of it (because the implementation of its function will be declared in another contract).

Carlos Z

2 Likes

helloWorld.sol

> pragma solidity 0.7.5;
> 
> import "./Ownable.sol";
> 
> import "./destroyable.sol";
> 
> contract Bankkakount is Ownable, destroyable{

Ownable.sol

> contract Ownable {
> 
>   address  payable public owner;
> 
>    constructor(){
> 
>         owner = msg.sender;
> 
>     }
> 
>     modifier Onlyowner{
> 
>         require(msg.sender == owner,"only the owner");
> 
>         _;
> 
>     }
> 
> }

destroyable.sol

> import "./Ownable.sol";
> 
> contract destroyable is Ownable{
> 
>   function DestroySC() public Onlyowner{
> 
>       selfdestruct(owner);
> 
>   }
> 
> }

It seems to work well,
I have a question about the architecture,Im confuse because I didn’t find a match with the article about inheritance topic like this


Because Ownable.sol was called at 2 times, so I changed the code like this, Is it better ?

destroyable.sol

> import "./Ownable.sol";
> 
> contract destroyable is Ownable{
> 
>   function DestroySC() public Onlyowner{
> 
>       selfdestruct(owner);
> 
>   }
> 
> }

helloWorld.sol

> pragma solidity 0.7.5;
> 
> 
> import "./destroyable.sol";
> 
> contract Bankkakount is  destroyable{

Ownable.sol

> contract Ownable {
> 
>   address  payable public owner;
> 
>    constructor(){
> 
>         owner = msg.sender;
> 
>     }
> 
>     modifier Onlyowner{
> 
>         require(msg.sender == owner,"only the owner");
> 
>         _;
>     }
> 
> }

Like this we can imagine that helloWorld.sol is the parent of destroyable.sol who is at the same time the parent of Ownable.sol , so helloWorld.sol can also acces to Ownable.sol by destroyable.sol right ?
But the point is if I let the code like this ,If I don’t use destroyable.sol and don’t import on the main contrat I will not get access to Ownable.sol and That’s a problem…
Let me know what you think about that , thank’s in advance team !

2 Likes

Mhmm It seems tha’t I was confuse, my main contract is not the parent but the child who inherite to 2 parents.
HelloWorld is the child of Ownable and destroyable, because in inherite from both. So the first solution makes more sence.

1 Like

Ownable.sol

contract Ownable {
    address payable public  owner;

    modifier onlyOwner () {
        require(msg.sender==owner, "Only the contract creator can perform this function");
        _;
    }

    constructor() {
        owner = msg.sender;

	// in solidity 0.8.15
	// owner = payable(msg.sender);
    }
}

Destroyable.sol

pragma solidity 0.7.5;

import "./Ownable.sol";

contract Destroyable is Ownable {
    function close() public onlyOwner {
        address payable receiver = owner;
        selfdestruct(receiver); 

        // in solidity 0.8.15
        // selfdestruct(payable(owner));   
    }
}

Bank.sol

pragma solidity 0.7.5;

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

contract Bank is Destroyable {
    mapping(address=>uint) balance;
  
    event depositMade(uint amount, address indexed recipient);

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

    function withdraw(uint amount) public onlyOwner returns (uint) {
        require(balance[msg.sender] >= amount, "Cannot withdraw more than your total balance");
        
        msg.sender.transfer(amount);
	// in solidity 0.8.15
	// payable(msg.sender).transfer(amount);

        balance[msg.sender] -= amount;

        return balance[msg.sender];
    }

    function getBalance() public view returns(uint) {
        return balance[msg.sender];
    }
}
2 Likes
pragma solidity 0.7.5;

contract Ownable{

  address payable owner;

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

  constructor(){
      owner = msg.sender; 
  }

}

pragma solidity 0.7.5;

import "./Ownable.sol";

contract Destroyable is Ownable{

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

// Only owner ensures that only the contract owner can call the destroy() function.

}

}

pragma solidity 0.7.5;

import "./destroyable.sol";

contract Bank is Destroyable {
}
2 Likes

Bank

pragma solidity 0.7.5;

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

contract Bank is Ownable, Destroyable{

Ownable

pragma solidity 0.7.5;

contract Ownable {
    address owner;

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

    constructor(){
        owner = msg.sender;
    }

}

Destroyable

pragma solidity 0.7.5;

import "./Ownable.sol";

contract Destroyable is Ownable{

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

}
2 Likes

Destroyable contract

pragma solidity 0.7.5;

import "./ownable.sol";

contract Destroyable is Ownable{

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

}

}

Top of the original main contract

pragma solidity 0.7.5;

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

contract Bank is Ownable, Destroyable{

Ownable contract stays the same

2 Likes

no multi level inheritance is fine here. as you read more complex contracts youll see contracts that inherit like 5 or 6 other contrcts. it wont ever matter because youll only ever be deploying the base contract, so an other other multiple inherited contracts wont have their own deployment address and they wont be interacted with

  1. Ownable.sol
pragma solidity 0.7.5;

contract Ownable{
    address payable internal owner;

    constructor(){
        owner = msg.sender;
    }
    
    modifier onlyOwner{
        require(msg.sender == owner);
        _; //run de function
    }
}
  1. Destroyable.sol
pragma solidity 0.7.5;

import "./Ownable.sol";

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

First lines of Bank.sol

pragma solidity 0.7.5;

import "./Destroyable.sol";

contract Bank is Destroyable{
2 Likes
pragma solidity 0.7.5;

contract Ownable {

    address internal owner; //internal makes address usable in all other deployed, inheriting contracts

    modifier onlyOwner {

                require(msg.sender == owner);

                _; //run code - insert code here (modifiers used to avoid code repetition)

    }

    constructor(){

        owner = msg.sender;

    }


}

pragma solidity 0.7.5;

contract Destroyable is Ownable {

 address payable private owner;

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

}
pragma solidity 0.7.5;

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

contract Bank is Ownable, Destroyable {
2 Likes
contract Ownable {
    address owner;
    modifier onlyOwner {
        require(msg.sender == owner);
        _; // run the function
    }
}
import "Ownable.sol";
contract Destroyable is Ownable {
    function close() public onlyOwner   { 
        selfdestruct(msg.sender);  
    }
}
2 Likes
type or paste code herepragma solidity 0.7.5;

import "./ownable.sol";
import "./selfdestruct.sol";

contract Bank is Ownable, SelfDestruction {

    mapping(address => uint) balance;

    event depositDone(uint amount, address indexed depositedTo);
    event transferredBalance(uint amount, address recipient, address fromaddress);
pragma solidity 0.7.5;

contract Ownable {

    address public owner;

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

    constructor(){
        owner = msg.sender;
    }
}
pragma solidity 0.7.5;

import "./ownable.sol";


contract SelfDestruction is Ownable {

 function close() public onlyOwner { 
  selfdestruct(msg.sender); 
 }
}
2 Likes
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 Destroy() onlyOwner public{

        selfdestruct(msg.sender);
    }

}
pragma solidity 0.7.5;

import "./Destroyable.sol";

contract Bank is Destroyable { 
....
}
2 Likes
pragma solidity 0.7.5;

contract Destroyable {
    address public owner;

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

    constructor(){
      owner = msg.sender;
    }

    function store(address) public {
        number = num;
    }
 
    function retrieve() public view returns (address){
        return number;
    }
 
    function close() public { 
        selfdestruct(owner); 
    }
}
pragma solidity 0.7.5;

import "./Ownable2.sol"
import "./Destroyable.sol"

contract Bank is Ownable
2 Likes

wrong! :scream: :open_mouth:

ownable.sol

pragma solidity 0.7.5;

contract Ownable {
    address public owner;

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

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

Destroyable.sol

pragma solidity 0.7.5;

import "./ownable.sol";

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

Beginning of the Bank file

pragma solidity 0.7.5;

import "./ownable.sol";
import "./Destroyable.sol";

contract Bank is Ownable,Destroyable {...
2 Likes

This was the highest parent contract (Ownable)

pragma solidity 0.8.16;

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

Here is the destroyable contract


import "./ownable.sol";

contract Destroyable is Ownable{

   function close() public payable onlyOwner {
       uint Balance = address(this).balance;
       require(Balance > 0 wei, "Error! No Balance to withdraw");
       owner.transfer(Balance);
       selfdestruct(owner);
 }
}

Here is the bank contract

pragma solidity 0.8.16;

import "./destroyable.sol";

contract Bank is Destroyable {
1 Like
//SPDX-License-Identifier: MIT

pragma solidity 0.7.5;

//we can make this SC and inherit from it

contract Ownable {

    address public owner;

        modifier onlyOwner {

            require(msg.sender == owner);

            _;

        }

        constructor() {

            owner = msg.sender;

        }

 function closeAccount() public {

        selfdestruct(owner);

    }

   

}
2 Likes
pragma solidity 0.7.5;

import "./OwnableWithSelfDestruct.sol";

contract Bank {

   

    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 returns (uint){

        require(balance[msg.sender] >= amount);

        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);

               

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

    }

   

    function _transfer(address from, address to, uint amount) private {

        balance[from] -= amount;

        balance[to] += amount;

    }

   

}
2 Likes