Inheritance & External Contracts - Discussion

  1. What is the base contract?
    Base contract is a parent contract.

  2. Which functions are available for derived contracts?
    For derived contract are available all public and internal scoped functions and state variables.

  3. What is hierarchical inheritance?
    Hierarchical inheritance is inheritance where multiple derived contracts inherit from single base contract.

1 Like

What is the base contract?

This is the parent contract that all derived contracts inherit from.

Which functions are available for derived contracts?

functions that are public or internal

What is hierarchical inheritance?

A base contract that has been extended by multiple derived contracts

1 Like

Hi I can’t figure out why my transfer function is not working. I get this error in the console

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.

Here is the 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 governmentInstance = GovernmentInterface(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4);
    
    mapping(address => uint) balance;
    
    event depositDone(uint amount, address depositedTo);
    
    event tokenTransfer(address from, address to, uint amount);
    
    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 Insufficient");
        uint prevBalance = balance[msg.sender];
        msg.sender.transfer(amount);
        balance[msg.sender] = prevBalance - amount;
        return(balance[msg.sender]);
    }
        
    
    function getBalance() public view returns(uint){
        return balance[msg.sender];
    }
    
    function transfer(address receipient, uint amount) public{
        require(balance[msg.sender] >= amount, "Balance Insufficient");
        require(msg.sender != receipient);
        
        uint prevSenderBalance = balance[msg.sender];
        
        _transfer(msg.sender, receipient, amount);
        
        governmentInstance.addTransaction(msg.sender, receipient, amount);
        
        assert(balance[msg.sender] == prevSenderBalance - amount);
        emit tokenTransfer(msg.sender, receipient, amount);
    }
    
    function _transfer(address from, address to, uint amount) private{
        balance[from] -= amount;
        balance[to] += amount;
    }
}


1 Like

Hey, @Jose_Hernandez, hope you are great.

Is your government contract deployed and you have the interface working?
If not, or dont want to use the government contract anymore, i suggest to delete it from the Bank contract.

If you have any more questions, please let us know so we can help you! :slight_smile:

Carlos Z.

Yes I deployed the government contract using a different address from the one used to deploy the bank contract.

I’ll try removing the government interface to isolate the code. Thanks!

1 Like

I tried removing the government interface and the transfer function worked just fine. I’ll rewatch the video to see where I got it wrong.

Another question, the transfer function only updates the balance from within the contract. Should there be a separate function to update the recipient address’ ether balance?

1 Like

Hey Jon,

Thanks for reaching out to me! I did tried once after the incident, but, I never tried again. I have been soaked with multiple assignments for the last month. Soon I will try and finish up that course.

Thanks again for the directions to resolve this issue!

2 Likes
  1. What is the base contract?
    The base contract is the contract that a derived contract inherits from. It is known as the parent contract.

  2. Which functions are available for derived contracts?
    Functions that are available in the base contract are available for derived contracts.

  3. What is hierarchical inheritance?
    Hierarchical inheritance is when a single contract acts as a base contract for multiple derived contracts.

1 Like

Not for your contract, every balance of each account is stored in the blockchain, including balances managed by a contract.

Carlos Z

1 Like

Thanks! I mixed up the balance of the address within the smart contract and its balance outside(remaining ether available).

  1. base contract is also known as parent contract. It’s the first contract from which all child contracts derive from
  2. all PUBLIC and INTERNAL scoped functions and state variables are available to derived contracts.
  3. in hierarchical inheritance, a single contract acts as a base contract for multiple derived contracts.
1 Like

Hi, Filip.

Perhaps this consideration will be covered later, but I’ll ask now, lest I forget. Prior to External contracts, the article on selfdestruct warned of losses if/when sending ETH to a destroyed contract. Isn’t this a concern that would be front and center, when interacting with External contracts? Is it just left to the eternal vigilance of the developer, or how does one stay abreast of any such updated, external contracts (and their destroyed predecessors)?

Many thanks,
Garrett.

  1. What is the base contract?

A base contract is also known as the parent contract from which child contracts inherit information.

  1. Which functions are available for derived contracts?

All public and internal scoped functions and state variables

  1. What is hierarchical inheritance?

Hierarchical inheritance means that a single contract can be a base contract to multiple contracts.

2 Likes
  1. Is the parent contract, from where the child contracts inherits from them.
  2. All public and internal scoped functions, as well as state variables are available to any derived contracts.
  3. Hierarchical inheritance is similar to simple inheritance. but the difference is that here in hierarchical inheritance, a single contract acts as a base contract for multiple derived contracts.
1 Like

Inheritance & External Contracts

What is the base contract?

The parent contract is known as a base contract.

Which functions are available for derived contracts?

There is a is-a relationship between base and derived contracts and all public and internal scoped

functions and state variables are available to derived contracts.

What is hierarchical inheritance?

A single contract acts as a base contract for multiple derived contracts.

1 Like
  1. The parent contract

  2. Can use all the function from the base contract except private functions

  3. It means that there is one base contract, with multiple derived contracts

1 Like

I can get the external govt contract to work fine but just entering the to and from address and the amount. I also have the banker contract to work by itself with the ownable contract inherited. When I add the interface and the create the instance it works.
But when I actually call the instance I get the error:

ā€œcall to government.getTransaction errored: VM error: invalid opcode. invalid opcode The execution might have thrown. Debug the transaction to get more informationā€

I have even added a owner function to the govt contract for it to print the address of the govt contract. to see if that was the problem but my address agrees to what was printed. Cant figure it out.

Here is the code for the govt contract

pragma  solidity 0.7.5;
contract government {
    
    address public govtowner1;
    
    struct Transaction{
        
        address from;
        address to;
        uint amount;
        uint txId;
    }
    
Transaction[]transactionLog;

function addTransaction(address _from, address _to, uint _amount) external{
    //Transaction memory _transaction = Transaction(_from, _to, _amount,transactionLog.length);
    //transactionLog.push(_transaction);//To save space you can combine this lin with the declaration statement
    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 );
   }
   
    constructor(){
        govtowner1 = msg.sender;
    }
  
   
   function govtowner() public view returns(address){
       
       return govtowner1;
   }
}

And here is the code for the bankermoney contract

pragma solidity 0.7.5;

import "./Ownable.sol";

interface GovernmentInterface{
//Here add the extenal function interface showing the name and parameters of the function.
   function addTransaction(address _from, address _to, uint amount) external; 
}


contract Bank is Ownable {
    
    GovernmentInterface governmentInstance = GovernmentInterface(0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB);
    
    mapping(address => uint) balance;

    
    //You can add an event function to use anywhere in the contract
    event depositDone(uint amount, address depositedTo);
    
    function deposit()public payable returns (uint){
        
        balance[msg.sender] += msg.value;
        
        //To emit an event you can call the event 
        
        emit depositDone(msg.value,msg.sender);
          return balance[msg.sender];
    }
    
    function withdraw(uint amount)public returns(uint){
        require(balance[msg.sender] >= amount, "Balance insufficien to make this transfer");
        msg.sender.transfer(amount);
        balance[msg.sender] = balance[msg.sender] - amount;
        return balance[msg.sender];
    }
    
    function getBalance()public view returns(uint){
        return balance[msg.sender];
        
    }
    
    function transfer(address recipient, uint amount) public {
      
      //check balance of msg.sender and the required also allows you to add statement if requirement not met.
       require(balance[msg.sender] >= amount,"Balance is not sufficient");
      
      // And now we can use require() to make sure that nobody except the owner can make a transfer
      require(msg.sender != recipient,"You cannot sent money to yourself");
     
       // We can also save the owners balance by adding a variable for previous balance before making transfer.
      uint previousBalance = balance[msg.sender];
       
       _transfer(msg.sender,recipient, amount);
       
       governmentInstance.addTransaction(msg.sender,recipient,amount);
      
       //And then we can use assert() to verifiy that the owner balance has been reduced by the transfer.
       //You cannot use a statement argument like for require
       
       assert(balance[msg.sender]== previousBalance - amount);
       
       
    
    //event logs and futher check will come later to check avaliable balances
    }
    
    function _transfer(address from, address to, uint amount)private {
        //Now you can reuse this code for ohter functions. Function can only be called within this contract
    
    balance[from] -= amount;
    balance[to] += amount;
    //emit balanceAdded(amount, to);
}


}
1 Like

Answers.

  1. The base contract is otherwise known as the parent contract.

  2. All public and internal scoped functions and state variables.

  3. Multiple contracts derived from the base contract/parent.

1 Like
  1. What is the base contract?
    The parent contract.
  2. Which functions are available for derived contracts?
    Public and internal scoped function.
  3. What is hierarchical inheritance?
    two child (sibling) contracts inheriting the same parent.
1 Like

Hey @Imhotep, hope you are great.

You have to deploy the government contract first and then change the bank contract interface address to the one you obtain after deploying the contract.

Click on that button to copy the contract address.
image

If you have any more questions, please let us know so we can help you! :slight_smile:

Carlos Z.