Inheritance & External Contracts - Discussion

@Jon
Hello again bud and thank you yet again, Sir!

First of all, I hope that you are ready to have a nice weekend. I just wanted to write to let you know that I am grateful for your valuable feedback and that I will get to work on the transfer function correction come Sunday. I’m aware that I need to rearrange the “require”, and "balance[msg.sender]"strings. Also, I have a few questions but before I post them I am going to mess with the code and do some experimenting as you suggest. I should be able to answer my own questions once I get my hands on it and put some time into experimenting with it.

Concerning the Inheritance task, I do not believe I am missing a semicolon, Jon. My good buddy Filip did not use it unless I missed it. I copied the code exactly the way he wrote it. Either way, I will make sure he did not use a semicolon after adding the code and get back asap.

Have a nice Friday!

1 Like

Thanks Joseph!

I hope you have a good weekend too!

You are definitely missing a semi colon, because Solidity’s syntax requires one at the end of each statement, and hopefully you can see that the error message generated by the compiler is telling you that one is missing.

// INCORRECT
import "./Ownable"

// CORRECT
import "./Ownable";

I’ve checked the 2nd video in this section (Inheritance) to see if there is a mistake that isn’t corrected, but Filip does add a semi colon at the end of this import statement (if you want to check it’s at 4:20).

Things like semi colons and brackets are easily missed, but the compiler picks these sorts of errors up for us as well, and the error messages help us to identify and correct them relatively painlessly.

1 Like

@jon_m
Indeed, you are absolutely right, bro. I stand corrected.

1 Like

Concerning tutorial 3, the inheritance assignment, I have pasted my code here. We were asked to code a contract titled “Destroyable” which is available only for the owner of the wallet. We were asked to add a function that inherits the self-destruct feature.

contract Destroyable{
    
    address payable public owner; 
    
    modifier onlyOwner{
        require(msg.sender ==owner); 
        _; 
        
    }
    
    constructor(){
        owner = msg.sender; 
    }
    
    function close() public {
        self-destruct(owner)
    }
    
}

@jon_m ,
Thanks for the feedbacks. The link I referred to that is not working is located at:

https://beta.ivanontech.com/topic/external-contracts-2
Link: https://vimeo.com/499438549/39820a3e76

You made a reference to me “jumping around a lot between the sections”. To explain, when I am faced with a trouble area or section I simply review the material again, in many case I have reviewed them more than twice. In addition I nearing the completion of going over the entire 101 course for the second time. So naturally I have questions from different sections which may explain “jumping around” like you stated. You also mentioned to “complete the assignments yourself before looking at the solutions”. My intent is the do that, I can only recall on two occasions when after making an effort I was not able to come up with a solution, so I looked ahead to understand the question and solution further. Lastly, you stated, “unless you submit your own code, you won’t receive any personalized feedback”. If you think I am submitting someone else’s code as my own work, then next time it would be helpful that you point out the specific code you are referring too. That statement did not come across very well and implied I submitted someone else’s code as my own. Thank you Jon.

2 Likes

Hi Karl,

Thanks for the reference for the link that doesn’t work. I didn’t realise it was on the new Academy beta version site. I’ll get that looked at :+1:

Thanks for explaining that. That makes sense now… and apologies for jumping to conclusions. In fact, you’ve done a great job in posting all of your questions in their different corresponding discussion threads.

I’m sorry it came across that way, Karl. That wasn’t what I meant at all. I was suggesting that posting your attempt at the assignment, or questions arising from your attempt, would give you some feedback and assistance before looking at the solution. If you get stuck or just don’t know where to begin with an assignment then I would also encourage you to spend some time looking at other students’ posts in the relevant forum discussion topic, with their attempts, solutions, and the help, comments and feedback they’ve received. There is a lot of helpful information here, and you will see that there are always several different alternative approaches and solutions to these assignments.

Anyway, it’s great that you are making good use of the forum to ask about some of the concepts you didn’t understand the first time around. I hope you’re getting the explanations and answers you need to clear up some of your remaining uncertainties. :slight_smile:

Fixed, thanks for notified it! :nerd_face:

Carlos Z

1 Like

Hi Joseph,

It is the selfdestruct() functionality that should only be available for the owner of the contract.
The problem is that anyone can call your close() function and destroy the contract. So you need to find a way to restrict access to this function so it can only be called by the contract owner.

Even though anyone can destroy the contract, you have ensured that the remaining ether balance will only be transferred to the contract owner. And well done for realising that you needed to make the owner address payable, so that selfdestruct() is called with a payable address. It needs to be a payable address so that it can receive the ether remaining in the contract when it is destroyed.

The aim of this assignment is to practise inheritance. So now try moving the contract ownership functionality back into a separate contract (Ownable) in a separate file (as you had before). You should have 3 separate contracts/files in total: (i) Ownable, (ii) Destroyable (now just containing the selfdestruct() functionality) and (iii) Bank. Then add the necessary code so that Bank inherits the selfdestruct() and contract ownership functionalities, and both are available when we just deploy Bank i.e. you should be able to deploy Bank, perform some transactions, then destroy the Bank contract, transferring any remaining ether balance to the caller of the selfdestruct function.

Once you’ve implemented this, we will also need to see what code you’ve added to the start of your Bank.sol file and Bank contract header for the inheritance.

Just a couple of other things…

The close() function you’ve added doesn’t inherit selfdestruct(), it contains it. It is this close() function that we want to be inherited by Bank (as explained above).

… and watch those semi colons! … you’re missing one again :wink:

Let me know if anything is unclear or if you have any questions.

Hi Jon

Still a little stuck in wanting the Litres to multiply by the PricePerLitre when I hit transact and appear when the show deal button is pressed… here is the code

pragma solidity 0.5.12;

contract OilContract{

struct Deal {
    string CompanyName;
    uint Litres;
    uint PricePerLitre;
    
}

mapping(address => Deal) private currentDeal;


//FUNCTIONS
function createDeal(string memory CompanyName, uint Litres, uint PricePerLitre) public {
  address creator = msg.sender;
  //This creates a Deal
  
   Deal memory newDeal;
   newDeal.CompanyName = CompanyName;
   newDeal.Litres = Litres;
   newDeal.PricePerLitre = PricePerLitre;

   
   currentDeal[creator] = newDeal;
}


function showDeal() public view returns(string memory CompanyName, uint Litres, uint PricePerLitre){
    address creator = msg.sender;        
    return(currentDeal[creator].CompanyName, currentDeal[creator].Litres, currentDeal[creator].PricePerLitre);
}

}

1 Like

Hi! Need a little help understanding what is going on here. I’m attempting to call an external payable function from remix – Code is inline. What am I missing here?

From contract testPiggy:
Actual Result: The value gets sent, but the contract balance is not updating when doing a “myDeposit” call from the “testPiggy” contract.
Expected Result: Value gets sent AND the contract balance is updated with the deposited amount.
From contract PiggyBank:
Actual Results: Both the value is sent and the contract balance is updated with deposited amount.

/*

//Problem: Only the deposit from within the PiggyBank works. The same function in here sends the either, BUT doesn’t get added the the contract balance.
// Where does the ether go when I call from the external function here during my test?
//
//File: TestPiggyBank.sol

*/

pragma solidity 0.8.1;

interface piggybankInterface{
function deposit() payable external returns (uint);
}

contract testPiggy{

piggybankInterface myBanker = piggybankInterface(0x0498B7c793D7432Cd9dB27fb02fc9cfdBAfA1Fd3);

function myDeposit() payable public returns (uint){
     
    return myBanker.deposit();
	}

function getContractBalance() public view returns(uint){

//Note: need to update to the deployed contract address.    
	return address(0x0498B7c793D7432Cd9dB27fb02fc9cfdBAfA1Fd3).balance; 
	}

}

/*

//Note: WORKS STANDALONE in remix. Ether balance goes to contract.
//File: PiggyBank.sol

*/

pragma solidity 0.8.1;

contract PiggyBank{

function deposit() payable external returns (uint){

    return msg.value;
 }

function getContractBalance() public view returns(uint){

	   return address(this).balance; 
}

}

Hi @CryptoDiddy,

First of all — nice contract :ok_hand:

If you don’t need to store the total price (litres x price per litre) in the mapping, and you just want to return it to the caller of showDeal(), then you just need to…

You can temporarily store the result of the multiplication calculation in a local variable…

// you can give this local variable whatever identifier (name) you want
uint totalPrice =
currentDeal[creator].Litres * currentDeal[creator].PricePerLitre;

As you already have a return statement, you just need to add a reference to the local variable in the return statement:

return(
    currentDeal[creator].CompanyName,
    currentDeal[creator].Litres, 
    currentDeal[creator].PricePerLitre,
    totalPrice    // references the value stored in the local variable
);

and then declare this additional return value in  returns()  in the function header:

returns(
    string memory CompanyName,
    uint Litres,
    uint PricePerLitre,
    uint total    // you can give this whatever identifier (name) you want
)

So, if you want to store the total price (litres x price per litre) in each Deal instance when it’s created, you need an extra property in the Deal struct e.g.  uint totalPrice;
and then, instead of assigning the result of the multiplication calculation to a local variable in the showDeal function, assign it to this additional property in each new Deal Instance created in the createDeal function:

newDeal.totalPrice = Litres * PricePerLitre;

If you do it this way, then you don’t need to perform the multiplication calculation in the showDeal function; you just need to reference the result that is already stored in the Deal instance’s extra property in the mapping:

return(
    currentDeal[creator].CompanyName,
    currentDeal[creator].Litres, 
    currentDeal[creator].PricePerLitre,
    currentDeal[creator].totalPrice   // references value stored in mapping
);

Thank you so much for your help… Had to go over it a few times and see where to fit it in and I got it to work

Thanks heaps

1 Like

Thanks Jon for the response and thanks for passing on the link to Carlos. He responded back saying that it is fixed, I will check it out shortly.

1 Like

@HanaYezi,

Hello Hana! Hope you are doing well. Just wanted to reach out and inquire about the inheritance task. I noticed that you completed this lesson under a month ago or so. Did you have any issues doing the inheritance task?

You’re very welcome, Nicholas,

Good… I wanted to leave some of the work to you, instead of just giving you the whole modified contract, because that way you’ll learn more from it :wink:

Yeh!! :raised_hands:

Hello everyone, I can’t seem to find where is the problem while declaring this interface. Can you guys help me out?

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

.1. Base contract is a parent contract

  1. These functions are available to derived contract:
    Public
    Internal
    And state variables

  2. Hierarchical. Inheritance is when a single contract act as a base contract for multiple derived contract

1 Like

Hi Atakan,

It’s difficult to tell what the problem is without seeing your complete Bank and Government contracts, and also not knowing what the error message is you’re getting, but the most common issue with this exercise is…

The Government contract needs to be deployed before Bank, and the Government contract’s address assigned to the  governmentInstance  state variable. If Government is redeployed at any stage, then it will have a different contract address, and the Government address previously assigned to  governmentInstance  will need to be updated to the new one before Bank is redeployed.

Another possible issue could be if your addTransaction function is called with an ether value. If so, it needs to be marked payable both in your Government contract and in the interface in Bank, otherwise the transaction will revert.

If these suggestions don’t solve your issue, post your complete code and the error message you’re getting and I’ll have a look at it for you :slight_smile:

Nice answers @michasuen :ok_hand:

Just one comment…

As with functions, state variables also need to have public or internal visibility to be inherited by derived contracts. State variables marked private are not available. On the other hand, all modifiers and all events in the parent contract are inheried.

Let me know if you have any questions :slight_smile:

@jon_m I found the problem and it was me being dumb :smiley:, I tried to define the interface inside the contract and that was why it was giving me errors, other than that it worked smoothly. Thanks for pointing out the possible errors, I checked them after I deployed contract and everything seems to be working. I just finished the 101 course yesterday and will probably start working on 201 next week. Thanks for helping out at every step :heart:

1 Like