Inheritance & External Contracts - Discussion

  1. What is the base contract?

The base contract is the child contract’s inherited contract (in code, child_con is base_con)

  1. Which functions are available for derived contracts?

Public and internal functions

  1. What is hierarchical inheritance?

Inheritance where one parent contract has many different child contracts

1 Like
  1. What is the base contract?
    The parent contract, that is inherited by the child contract, is known as the base contract.

  2. Which functions are available for derived contracts?
    All public and internal scoped functions and state variables are available to derived contracts

  3. What is hierarchical inheritance?
    A parent contract acts as a base contract for multiple derived child contracts.

Hey, thanks for your help @thecil! I ended up figuring it out on my own, thankfully.

1 Like

Hi all,
I was doing the second inheritance assignment and I had an error that i do not understand
If anyone could explain me what i did wrong I would be greatful.
I pass the my code from my Bank.sol, ownAble.sol and destroyable.sol here.

Bank.sol:
// SPDX-License-Identifier: MIT
pragma solidity 0.7.5;

import “./ownAble.sol”;
import “./destroyable.sol”;
contract PlikiPliki is ownAble, destroyable {

mapping(address=>uint) balance;

event depositDone(uint amount, address indexed depositedTo);
event transferMade(address from, address to, uint amounTransered);


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

function withdraw(uint amount) public returns(uint){
    //require(amount <= balance[msg.sender]);
    msg.sender.transfer(amount);
    //balance[msg.sender] -= amount;
    return balance[msg.sender];
}

function transfer(address recipient, uint amount) public{
    //some important checks
    require(msg.sender != recipient);
    require(balance[msg.sender] >= amount);
    
    uint balanceBeforeTransfer = balance[msg.sender];
    _transfer(msg.sender, recipient, amount);
    
    //some other contract logic;
    assert(balanceBeforeTransfer == balance[msg.sender] + amount);
    emit transferMade(msg.sender, recipient, amount);
}

function _transfer(address from, address to, uint amount) private{
    balance[from] -= amount;
    balance[to] += amount;
}

}
ownAble.sol:
// SPDX-License-Identifier: MIT
pragma solidity 0.7.5;

contract ownAble {

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

constructor(){
    owner = msg.sender;
}

}

destroyAble.sol:
// SPDX-License-Identifier: MIT
import “./ownAble.sol”;
pragma solidity >0.6.0;
contract Storage is ownAble {
function close() public {
selfdestruct(owner);
}
}

What is the base contract?

Inheritance defines multiple parent-child relationships between different contracts. The base contract is the one that is inherited (the contract that inherits is called the child contract).

Which functions are available for derived contracts?

All public and internal scoped functions and state variables are available to derived contracts

What is hierarchical inheritance?

A hierarchical inheritance is when a single contract acts as a base contract (parent) of many derived contracts.

1 Like

pragma solidity 0.7.5;

contract Ownable {
address owner;

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

constructor(){
    owner = msg.sender;
}

}

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

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

pragma solidity 0.7.5;

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

contract Bank20 is Ownable, Destroyable{

mapping(address => uint) balance;

event depositDone(uint amount, address indexed depositTo);

function getContractBalance() public view returns(uint) {
return address(this).balance;
}

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);
msg.sender.transfer(amount);
return balance[msg.sender];
}

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

What’s not working here is the getBalance() function.
I can deposit and withdraw. When I deposit the getBalance() function is updating the deposit. When I withdraw the getBalance() function is not updating. The getContractBalance however is updating after deposit and withdraw. i only realized that now (not during the withDraw assignment…) and couldn’t figure out why that is. Can you help? thank you.

1 Like

Bank Contract

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

contract Bank is Ownable, Destroyable {
...
}

Ownable Contract

contract Ownable {
    // adding public to a state variable will automatically create a function that will allow you to access the variable
    address payable public owner;
    
    modifier onlyOwner {
        require(msg.sender == owner);
        _; //run the function
    }
    
    constructor() {
        owner = msg.sender;
    }
}

Destroyable Contract

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

I’m getting following error when trying to transfer an amount.
edit: Error has been fixed. I had the wallet address that deployed the contract set at GovernmentInterface instead of the contract address itself.

transact to Bank.transfer errored: VM error: revert.

revert
The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the value you send should be less than your current balance.
Debug the transaction to get more information.
creation of Bank pending…

Here is my code:

pragma solidity 0.7.5;

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

interface GovernmentInterface{
function addTransaction(address _from, address _to, uint _amount) external;
}

contract Bank is Ownable, SelfDestruct {

GovernmentInterface GovernmentInstance = GovernmentInterface(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4);

mapping(address => uint) balance;

event depositDone(uint amount, address indexed depostiedTo);
event amountTransfered(uint amount, address indexed transferedTo, address indexed transferedFrom);

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, “The amount you tried to withdraw is bigger than your balance”);
uint previousSenderBalance = balance[msg.sender];
balance[msg.sender] -= amount;
msg.sender.transfer(amount);
assert(balance[msg.sender] == previousSenderBalance - 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);

GovernmentInstance.addTransaction(msg.sender, recipient, amount);
emit amountTransfered(amount, recipient, msg.sender);
assert(balance[msg.sender] == previousSenderBalance - amount);
  //event Logs and further checks

}

function _transfer(address from, address to, uint amount) private {
balance[from] -= amount;
balance[to] += amount;
}

}

pragma solidity 0.7.5;

contract Government {

struct Transaction {
    address from;
    address to;
    uint amount;
    uint txId;
}

Transaction[] transactionLog;

function addTransaction(address _from, address _to, uint _amount) external {
      transactionLog.push( Transaction(_from, _to, _amount, transactionLog.length) );
}
function getTransaction(uint _index) public view returns(address, address, uint) {
    return(transactionLog[_index].from, transactionLog[_index].to, transactionLog[_index].amount);

}
}

1 Like

In the video of Value calls Filip talks about the value of wei, gwei and ether. In Remix there is also an option to add finney. What’s the value of this?

1 Like

Basically it refers to this: (ether denominations)
image

Carlos Z

1 Like

Hmm. I am getting this error as well. Here is my code:

pragma solidity 0.7.5;
 
 import "./Ownable.sol";
 
 
 interface GovernmentInterface{
     function addTransaction(address _from, address _to, uint _amount) external;
 }
 
 contract Bank is Ownable{
     
    GovernmentInterface governmentInsatance = GovernmentInterface(0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c);
     
    mapping(address => uint) balance;
    
    
    
    event depositDone(uint amount, address depositedTo);
    event amountTransfered(uint amount, address trasferedFrom, address trasferedTo);
    
   
    
   
    
    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, "Balance not sufficent!" );
        msg.sender.transfer(amount);
        balance[msg.sender] -= amount;
        return balance[msg.sender];
    }
     
     function getBalance() public view returns (uint){
         return balance[msg.sender];
     }
     
     function transfer(address recipeint, uint amount) public {
         require(balance[msg.sender] >= amount, "Balance not sufficent!" );
         require(msg.sender != recipeint);
         
         uint previousSenderBalance = balance[msg.sender];
         
         _transfer(msg.sender, recipeint, amount);
         
         governmentInsatance.addTransaction(msg.sender, recipeint, amount);
         
         
         
         assert(balance[msg.sender] == previousSenderBalance - amount);
         //event logs and further checks
         
     }
     
     function _transfer(address from, address to, uint amount) private{
         balance[from] -= amount;
         balance[to] += amount;
     }
     
 }


pragma solidity 0.7.5;


contract Government{
    
    struct Transaction {
        address from;
        address to;
        uint amount;
        uint txId;
    }
    
    Transaction[] transactionLog;
    
    function addTransaction(address _from, address _to, uint _amount) external{
        transactionLog.push(Transaction(_from, _to, _amount, transactionLog.length));
        
    }
    
    function getTransaction(uint _index) public view returns(address, address, uint){
        return(transactionLog[_index].from,transactionLog[_index].to, transactionLog[_index].amount);
        
    }
    
}
pragma solidity 0.7.5;


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

image

That might be a require condition that is triggered but does not contain a revert message, you should check the transfer function.

Carlos Z

1 Like

hiii what is the use of value as we are having amount as argument already .what is the difference between two?

you mean using msg.value against a argument amount?

The first one is used only when the function is payable, then msg.value can be used to store the amount of ethers that the contract will receive, while the argument can be used with or without the payable keyword and ot can not store funds (ethers) like msg.value does.

Carlos Z

pragma solidity 0.7.5;

contract Ownable {
    
    address payable owner;
    
    modifier onlyOwner {
        require(msg.sender == owner, "Only the contract creator can call this function.");
        _; // run the function code
    }
    
    constructor() {
        owner = msg.sender;
    }
}
pragma solidity 0.7.5;

import "./ownable.sol";

contract Destroyable is Ownable {
    
    function destroy() internal onlyOwner {
        selfdestruct(owner);
    }
}
pragma solidity 0.7.5;

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

contract Bank is Destroyable {
    /** Old code */
    
    function terminate() public {
        destroy();
    }
}
1 Like

I’m getting the same error as others. I commented out the requires and still have the same issue.

function transfer(address recipient, uint amount) public {
        // require(balance[msg.sender] >= amount);
        // require(msg.sender != recipient);
        
        uint prevSenderBalance = balance[msg.sender];
        uint prevRecipientBalance = balance[recipient];
        
        _transfer(msg.sender, recipient, amount);
        
        govInstance.addTransaction(msg.sender, recipient, amount);
        
        // assert(balance[msg.sender] == prevSenderBalance + amount);
        // assert(balance[recipient] == prevRecipientBalance + amount);
    }

Hey @Tomster, hope you are ok.

What about that interface? It could be that the contract address is not correct, also if the function is payable, you could remove it if you are not planning to sent any funds to it.

Carlos Z

Hey Carlos I found a typo in my code :man_facepalming: where I was trying to assert that the amount was subtracted from senders balance but instead of using subtract I added the amount in the assert.

uint prevSenderBalance = balance[msg.sender];

_transfer(msg.sender, recipient, amount);
govInstance.addTransaction(msg.sender, recipient, amount);

assert(balance[msg.sender] == prevSenderBalance + amount); // Should be subtract not add
1 Like

Q.1.What is the base contract?
A.1 Is a parent contract or the contract has the ability to be inherited by other contracts.

Q.2.Which functions are available for derived contracts?
A.2. Internal and Public funcitons

Q.3.What is hierarchical inheritance?
A.3 A single contract acts as base contract for one or more derived contracts

1 Like

I have been working on a simple bank contract that give a 5 percent daily interested for the total of one monthly but am finding it hard to avoid the error now my major problem is how to input a code that can execute the function of the daily interested for the duration of one month
please I need help anybody that can help me out please